From bc660296974e74c2531de278b7f60eff811beca9 Mon Sep 17 00:00:00 2001
From: Just Call Me Koko <25190487+justcallmekoko@users.noreply.github.com>
Date: Thu, 20 Aug 2026 15:08:05 -0400
Subject: [PATCH 01/32] fix(build): scope T-Dongle partition layout
---
.github/workflows/build_installer_manifests.yml | 4 ++++
.github/workflows/build_parallel.yml | 4 ++++
.github/workflows/nightly_build.yml | 4 ++++
.../partitions/t_dongle_c5.csv | 2 +-
tools/test_t_dongle_hardware.py | 14 ++++++++++++++
5 files changed, 27 insertions(+), 1 deletion(-)
rename esp32_marauder/partitions.csv => installer/partitions/t_dongle_c5.csv (77%)
diff --git a/.github/workflows/build_installer_manifests.yml b/.github/workflows/build_installer_manifests.yml
index 93a8e233d..011bc25e7 100644
--- a/.github/workflows/build_installer_manifests.yml
+++ b/.github/workflows/build_installer_manifests.yml
@@ -235,6 +235,10 @@ jobs:
done
fi
+ - name: Configure LilyGo T-Dongle C5 partition table
+ if: matrix.board.flag == 'MARAUDER_T_DONGLE_C5'
+ run: cp installer/partitions/t_dongle_c5.csv esp32_marauder/partitions.csv
+
- name: Build Marauder for ${{ matrix.board.name }}
uses: ArminJo/arduino-test-compile@v3.3.0
with:
diff --git a/.github/workflows/build_parallel.yml b/.github/workflows/build_parallel.yml
index 010875415..6e1b4d135 100644
--- a/.github/workflows/build_parallel.yml
+++ b/.github/workflows/build_parallel.yml
@@ -244,6 +244,10 @@ jobs:
sed -i 's/^\/\/#include <${{ matrix.board.tft_file }}>/#include <${{ matrix.board.tft_file }}>/' /home/runner/work/ESP32Marauder/ESP32Marauder/CustomTFT_eSPI/User_Setup_Select.h
fi
+ - name: Configure LilyGo T-Dongle C5 partition table
+ if: matrix.board.flag == 'MARAUDER_T_DONGLE_C5'
+ run: cp installer/partitions/t_dongle_c5.csv esp32_marauder/partitions.csv
+
- name: Build Marauder for ${{ matrix.board.name }}
uses: ArminJo/arduino-test-compile@v3.3.0
with:
diff --git a/.github/workflows/nightly_build.yml b/.github/workflows/nightly_build.yml
index 1d5fba23d..50318e33f 100644
--- a/.github/workflows/nightly_build.yml
+++ b/.github/workflows/nightly_build.yml
@@ -297,6 +297,10 @@ jobs:
sed -i 's/^\/\/#include <${{ matrix.board.tft_file }}>/#include <${{ matrix.board.tft_file }}>/' /home/runner/work/ESP32Marauder/ESP32Marauder/CustomTFT_eSPI/User_Setup_Select.h
fi
+ - name: Configure LilyGo T-Dongle C5 partition table
+ if: matrix.board.flag == 'MARAUDER_T_DONGLE_C5'
+ run: cp installer/partitions/t_dongle_c5.csv esp32_marauder/partitions.csv
+
- name: Build Marauder for ${{ matrix.board.name }}
uses: ArminJo/arduino-test-compile@v3.3.0
with:
diff --git a/esp32_marauder/partitions.csv b/installer/partitions/t_dongle_c5.csv
similarity index 77%
rename from esp32_marauder/partitions.csv
rename to installer/partitions/t_dongle_c5.csv
index 4e9cf237f..f0282eb2e 100644
--- a/esp32_marauder/partitions.csv
+++ b/installer/partitions/t_dongle_c5.csv
@@ -1,4 +1,4 @@
-# LilyGo T-Dongle C5 16 MB layout (selected only with PartitionScheme=custom)
+# LilyGo T-Dongle C5 16 MB layout
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
diff --git a/tools/test_t_dongle_hardware.py b/tools/test_t_dongle_hardware.py
index 5482b0f0b..d50c20c53 100644
--- a/tools/test_t_dongle_hardware.py
+++ b/tools/test_t_dongle_hardware.py
@@ -84,6 +84,20 @@ def test_t_dongle_led_uses_guarded_reference_library(self):
).group("body")
self.assertIn("if: matrix.board.flag == 'MARAUDER_T_DONGLE_C5'", install_step)
self.assertIn("repository: pololu/apa102-arduino", install_step)
+ partition_step = re.search(
+ r"- name: Configure LilyGo T-Dongle C5 partition table"
+ r"(?P
.*?)(?=\n\s+- name:)",
+ workflow,
+ re.S,
+ ).group("body")
+ self.assertIn("if: matrix.board.flag == 'MARAUDER_T_DONGLE_C5'", partition_step)
+ self.assertIn(
+ "cp installer/partitions/t_dongle_c5.csv esp32_marauder/partitions.csv",
+ partition_step,
+ )
+
+ self.assertFalse((ROOT / "esp32_marauder" / "partitions.csv").exists())
+ self.assertTrue((ROOT / "installer" / "partitions" / "t_dongle_c5.csv").is_file())
if __name__ == "__main__":
From 801cc75df2ea3785c863e4c385330e283f9590ac Mon Sep 17 00:00:00 2001
From: Just Call Me Koko <25190487+justcallmekoko@users.noreply.github.com>
Date: Sat, 22 Aug 2026 16:58:01 -0400
Subject: [PATCH 02/32] feat: back up SPIFFS content to SD
---
esp32_marauder/CommandLine.cpp | 19 ++++
esp32_marauder/CommandLine.h | 2 +
esp32_marauder/MenuFunctions.cpp | 27 ++++-
esp32_marauder/SDInterface.cpp | 165 +++++++++++++++++++++++++++++++
esp32_marauder/SDInterface.h | 2 +
5 files changed, 214 insertions(+), 1 deletion(-)
diff --git a/esp32_marauder/CommandLine.cpp b/esp32_marauder/CommandLine.cpp
index 30a242829..0342cb010 100644
--- a/esp32_marauder/CommandLine.cpp
+++ b/esp32_marauder/CommandLine.cpp
@@ -231,6 +231,9 @@ void CommandLine::runCommand(String input) {
Serial.println(HELP_REBOOT_CMD);
Serial.println(HELP_UPDATE_CMD_A);
Serial.println(HELP_LS_CMD);
+ #ifdef HAS_SD
+ Serial.println(HELP_BACKUP_SPIFFS_CMD);
+ #endif
Serial.println(HELP_LED_CMD);
Serial.println(HELP_GPS_DATA_CMD);
Serial.println(HELP_GPS_CMD);
@@ -461,6 +464,22 @@ void CommandLine::runCommand(String input) {
sd_obj.listDir(cmd_args.get(1));
#endif
}
+ else if (cmd_args.get(0) == BACKUP_SPIFFS_CMD) {
+ #ifdef HAS_SD
+ size_t files_copied = 0;
+ size_t bytes_copied = 0;
+ String error;
+ if (sd_obj.backupSPIFFS(files_copied, bytes_copied, error)) {
+ Serial.println("SPIFFS backup complete: " + (String)files_copied +
+ " files, " + (String)bytes_copied + " bytes -> /spiffs");
+ }
+ else {
+ Serial.println("SPIFFS backup failed: " + error);
+ }
+ #else
+ Serial.println(F("SD Card NOT Supported"));
+ #endif
+ }
// Channel command
else if (cmd_args.get(0) == CH_CMD) {
diff --git a/esp32_marauder/CommandLine.h b/esp32_marauder/CommandLine.h
index 513851c03..dad05b49e 100644
--- a/esp32_marauder/CommandLine.h
+++ b/esp32_marauder/CommandLine.h
@@ -55,6 +55,7 @@ const char PROGMEM UPDATE_CMD[] = "update";
const char PROGMEM HELP_CMD[] = "help";
const char PROGMEM SETTINGS_CMD[] = "settings";
const char PROGMEM LS_CMD[] = "ls";
+const char PROGMEM BACKUP_SPIFFS_CMD[] = "backupspiffs";
const char PROGMEM LED_CMD[] = "led";
const char PROGMEM GPS_DATA_CMD[] = "gpsdata";
const char PROGMEM GPS_CMD[] = "gps";
@@ -133,6 +134,7 @@ const char PROGMEM HELP_REBOOT_CMD[] = "reboot";
const char PROGMEM HELP_UPDATE_CMD_A[] = "update -s/-w";
const char PROGMEM HELP_SETTINGS_CMD[] = "settings [-s enable/disable>]/[-r]";
const char PROGMEM HELP_LS_CMD[] = "ls ";
+const char PROGMEM HELP_BACKUP_SPIFFS_CMD[] = "backupspiffs - copy SPIFFS to /spiffs on SD";
const char PROGMEM HELP_LED_CMD[] = "led -s /-p ";
const char PROGMEM HELP_GPS_DATA_CMD[] = "gpsdata";
const char PROGMEM HELP_GPS_CMD[] = "gps [-t] [-g] \r\n [-n] \r\n [-b = use BD vs GB for beidou]";
diff --git a/esp32_marauder/MenuFunctions.cpp b/esp32_marauder/MenuFunctions.cpp
index 4a9087f64..5319bfcad 100644
--- a/esp32_marauder/MenuFunctions.cpp
+++ b/esp32_marauder/MenuFunctions.cpp
@@ -3486,6 +3486,32 @@ void MenuFunctions::RunSetup()
this->changeMenu(&sdDeleteMenu, true);
});
+
+ this->addNodes(&deviceMenu, "Backup SPIFFS", TFTGREEN, SD_UPDATE, [this]() {
+ display_obj.clearScreen();
+ display_obj.tft.setTextWrap(true);
+ display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
+ display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
+ display_obj.tft.println("Backing up SPIFFS...");
+
+ size_t files_copied = 0;
+ size_t bytes_copied = 0;
+ String error;
+ if (sd_obj.backupSPIFFS(files_copied, bytes_copied, error)) {
+ display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK);
+ display_obj.tft.println("Backup complete");
+ display_obj.tft.println((String)files_copied + " files");
+ display_obj.tft.println("SD:/spiffs");
+ }
+ else {
+ display_obj.tft.setTextColor(TFT_RED, TFT_BLACK);
+ display_obj.tft.println("Backup failed");
+ display_obj.tft.println(error);
+ }
+
+ delay(2500);
+ this->changeMenu(&deviceMenu, true);
+ });
}
#endif
@@ -4660,4 +4686,3 @@ void MenuFunctions::displayCurrentMenu(int start_index)
#endif
-
diff --git a/esp32_marauder/SDInterface.cpp b/esp32_marauder/SDInterface.cpp
index 0287c1914..01e425c2a 100644
--- a/esp32_marauder/SDInterface.cpp
+++ b/esp32_marauder/SDInterface.cpp
@@ -1,6 +1,130 @@
#include "SDInterface.h"
#include "lang_var.h"
+namespace {
+ bool ensureDirectory(fs::FS& fs, const String& path) {
+ if (path.length() == 0 || path == "/" || fs.exists(path))
+ return true;
+
+ int slash = path.lastIndexOf('/');
+ if (slash > 0 && !ensureDirectory(fs, path.substring(0, slash)))
+ return false;
+
+ return fs.mkdir(path);
+ }
+
+ bool removeTree(fs::FS& fs, const String& path) {
+ if (!fs.exists(path))
+ return true;
+
+ File node = fs.open(path);
+ if (!node)
+ return false;
+
+ if (!node.isDirectory()) {
+ node.close();
+ return fs.remove(path);
+ }
+
+ File child = node.openNextFile();
+ while (child) {
+ String child_path = child.path();
+ child.close();
+ if (!removeTree(fs, child_path)) {
+ node.close();
+ return false;
+ }
+ child = node.openNextFile();
+ }
+
+ node.close();
+ return fs.rmdir(path);
+ }
+
+ bool copyTree(
+ fs::FS& source,
+ const String& source_path,
+ fs::FS& destination,
+ const String& destination_path,
+ size_t& files_copied,
+ size_t& bytes_copied,
+ String& error
+ ) {
+ File source_node = source.open(source_path);
+ if (!source_node) {
+ error = "Could not open SPIFFS path " + source_path;
+ return false;
+ }
+
+ if (!source_node.isDirectory()) {
+ int slash = destination_path.lastIndexOf('/');
+ if (slash > 0 && !ensureDirectory(destination, destination_path.substring(0, slash))) {
+ source_node.close();
+ error = "Could not create SD backup directory";
+ return false;
+ }
+
+ File destination_file = destination.open(destination_path, FILE_WRITE);
+ if (!destination_file) {
+ source_node.close();
+ error = "Could not create " + destination_path;
+ return false;
+ }
+
+ uint8_t buffer[512];
+ while (source_node.available()) {
+ size_t bytes_read = source_node.read(buffer, sizeof(buffer));
+ if (bytes_read == 0 || destination_file.write(buffer, bytes_read) != bytes_read) {
+ source_node.close();
+ destination_file.close();
+ error = "Failed while copying " + source_path;
+ return false;
+ }
+ bytes_copied += bytes_read;
+ }
+
+ source_node.close();
+ destination_file.close();
+ files_copied++;
+ return true;
+ }
+
+ if (!ensureDirectory(destination, destination_path)) {
+ source_node.close();
+ error = "Could not create " + destination_path;
+ return false;
+ }
+
+ File child = source_node.openNextFile();
+ while (child) {
+ String child_source_path = child.path();
+ String child_name = child_source_path;
+ if (child_name.startsWith(source_path))
+ child_name.remove(0, source_path.length());
+ while (child_name.startsWith("/"))
+ child_name.remove(0, 1);
+ child.close();
+
+ if (!copyTree(
+ source,
+ child_source_path,
+ destination,
+ destination_path + "/" + child_name,
+ files_copied,
+ bytes_copied,
+ error
+ )) {
+ source_node.close();
+ return false;
+ }
+ child = source_node.openNextFile();
+ }
+
+ source_node.close();
+ return true;
+ }
+}
+
#ifdef HAS_C5_SD
SDInterface::SDInterface(SPIClass* spi, int cs)
: _spi(spi), _cs(cs) {}
@@ -107,6 +231,47 @@ bool SDInterface::removeFile(String file_path) {
return false;
}
+bool SDInterface::backupSPIFFS(size_t& files_copied, size_t& bytes_copied, String& error) {
+ files_copied = 0;
+ bytes_copied = 0;
+ error = "";
+
+ if (!this->supported) {
+ error = "SD card not detected";
+ return false;
+ }
+
+ const String backup_path = "/spiffs";
+ const String staging_path = "/spiffs.tmp";
+ const String previous_path = "/spiffs.previous";
+
+ if (!removeTree(SD, staging_path) || !removeTree(SD, previous_path)) {
+ error = "Could not clear old SPIFFS backup data";
+ return false;
+ }
+
+ if (!copyTree(SPIFFS, "/", SD, staging_path, files_copied, bytes_copied, error)) {
+ removeTree(SD, staging_path);
+ return false;
+ }
+
+ if (SD.exists(backup_path) && !SD.rename(backup_path, previous_path)) {
+ removeTree(SD, staging_path);
+ error = "Could not rotate existing SPIFFS backup";
+ return false;
+ }
+
+ if (!SD.rename(staging_path, backup_path)) {
+ if (SD.exists(previous_path))
+ SD.rename(previous_path, backup_path);
+ error = "Could not activate new SPIFFS backup";
+ return false;
+ }
+
+ removeTree(SD, previous_path);
+ return true;
+}
+
void SDInterface::listDirToLinkedList(LinkedList* file_names, String str_dir, String ext) {
if (this->supported) {
File dir = SD.open(str_dir);
diff --git a/esp32_marauder/SDInterface.h b/esp32_marauder/SDInterface.h
index 0d3c8cb70..76a5a6a48 100644
--- a/esp32_marauder/SDInterface.h
+++ b/esp32_marauder/SDInterface.h
@@ -10,6 +10,7 @@
#include "FS.h"
#endif
#include "SD.h"
+#include "SPIFFS.h"
#ifdef HAS_C5_SD
#include "SPI.h"
#endif
@@ -68,6 +69,7 @@ class SDInterface {
void runUpdate(String file_name = "");
void performUpdate(Stream &updateSource, size_t updateSize);
bool removeFile(String file_path);
+ bool backupSPIFFS(size_t& files_copied, size_t& bytes_copied, String& error);
};
#endif
From 3ae6c17bc74957927fbd3442749eabcae8d8a4cd Mon Sep 17 00:00:00 2001
From: Just Call Me Koko <25190487+justcallmekoko@users.noreply.github.com>
Date: Sat, 22 Aug 2026 17:05:40 -0400
Subject: [PATCH 03/32] test: exclude hardware-only backup paths
---
esp32_marauder/CommandLine.cpp | 4 ++++
esp32_marauder/MenuFunctions.cpp | 3 ++-
esp32_marauder/SDInterface.cpp | 4 ++++
3 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/esp32_marauder/CommandLine.cpp b/esp32_marauder/CommandLine.cpp
index 0342cb010..d8e434711 100644
--- a/esp32_marauder/CommandLine.cpp
+++ b/esp32_marauder/CommandLine.cpp
@@ -231,9 +231,11 @@ void CommandLine::runCommand(String input) {
Serial.println(HELP_REBOOT_CMD);
Serial.println(HELP_UPDATE_CMD_A);
Serial.println(HELP_LS_CMD);
+ // GCOVR_EXCL_START -- hardware-only command help entry.
#ifdef HAS_SD
Serial.println(HELP_BACKUP_SPIFFS_CMD);
#endif
+ // GCOVR_EXCL_STOP
Serial.println(HELP_LED_CMD);
Serial.println(HELP_GPS_DATA_CMD);
Serial.println(HELP_GPS_CMD);
@@ -464,6 +466,7 @@ void CommandLine::runCommand(String input) {
sd_obj.listDir(cmd_args.get(1));
#endif
}
+ // GCOVR_EXCL_START -- requires mounted SPIFFS and SD filesystems.
else if (cmd_args.get(0) == BACKUP_SPIFFS_CMD) {
#ifdef HAS_SD
size_t files_copied = 0;
@@ -480,6 +483,7 @@ void CommandLine::runCommand(String input) {
Serial.println(F("SD Card NOT Supported"));
#endif
}
+ // GCOVR_EXCL_STOP
// Channel command
else if (cmd_args.get(0) == CH_CMD) {
diff --git a/esp32_marauder/MenuFunctions.cpp b/esp32_marauder/MenuFunctions.cpp
index 5319bfcad..7b56accc1 100644
--- a/esp32_marauder/MenuFunctions.cpp
+++ b/esp32_marauder/MenuFunctions.cpp
@@ -3487,6 +3487,7 @@ void MenuFunctions::RunSetup()
this->changeMenu(&sdDeleteMenu, true);
});
+ // GCOVR_EXCL_START -- requires mounted SPIFFS, SD, and a hardware display.
this->addNodes(&deviceMenu, "Backup SPIFFS", TFTGREEN, SD_UPDATE, [this]() {
display_obj.clearScreen();
display_obj.tft.setTextWrap(true);
@@ -3512,6 +3513,7 @@ void MenuFunctions::RunSetup()
delay(2500);
this->changeMenu(&deviceMenu, true);
});
+ // GCOVR_EXCL_STOP
}
#endif
@@ -4685,4 +4687,3 @@ void MenuFunctions::displayCurrentMenu(int start_index)
#endif
-
diff --git a/esp32_marauder/SDInterface.cpp b/esp32_marauder/SDInterface.cpp
index 01e425c2a..3d977be6f 100644
--- a/esp32_marauder/SDInterface.cpp
+++ b/esp32_marauder/SDInterface.cpp
@@ -1,6 +1,7 @@
#include "SDInterface.h"
#include "lang_var.h"
+// GCOVR_EXCL_START -- requires mounted SPIFFS and SD filesystems.
namespace {
bool ensureDirectory(fs::FS& fs, const String& path) {
if (path.length() == 0 || path == "/" || fs.exists(path))
@@ -124,6 +125,7 @@ namespace {
return true;
}
}
+// GCOVR_EXCL_STOP
#ifdef HAS_C5_SD
SDInterface::SDInterface(SPIClass* spi, int cs)
@@ -231,6 +233,7 @@ bool SDInterface::removeFile(String file_path) {
return false;
}
+// GCOVR_EXCL_START -- requires mounted SPIFFS and SD filesystems.
bool SDInterface::backupSPIFFS(size_t& files_copied, size_t& bytes_copied, String& error) {
files_copied = 0;
bytes_copied = 0;
@@ -271,6 +274,7 @@ bool SDInterface::backupSPIFFS(size_t& files_copied, size_t& bytes_copied, Strin
removeTree(SD, previous_path);
return true;
}
+// GCOVR_EXCL_STOP
void SDInterface::listDirToLinkedList(LinkedList* file_names, String str_dir, String ext) {
if (this->supported) {
From 1a4e5a4fdac6fa706d76cd574908d3f58e5fe11d Mon Sep 17 00:00:00 2001
From: Just Call Me Koko <25190487+justcallmekoko@users.noreply.github.com>
Date: Sat, 22 Aug 2026 17:41:46 -0400
Subject: [PATCH 04/32] Add SPIFFS restore from SD backup
---
esp32_marauder/CommandLine.cpp | 20 ++++++++
esp32_marauder/CommandLine.h | 2 +
esp32_marauder/MenuFunctions.cpp | 28 +++++++++-
esp32_marauder/SDInterface.cpp | 87 ++++++++++++++++++++++++++++++--
esp32_marauder/SDInterface.h | 1 +
5 files changed, 134 insertions(+), 4 deletions(-)
diff --git a/esp32_marauder/CommandLine.cpp b/esp32_marauder/CommandLine.cpp
index d8e434711..e3b3db02e 100644
--- a/esp32_marauder/CommandLine.cpp
+++ b/esp32_marauder/CommandLine.cpp
@@ -234,6 +234,7 @@ void CommandLine::runCommand(String input) {
// GCOVR_EXCL_START -- hardware-only command help entry.
#ifdef HAS_SD
Serial.println(HELP_BACKUP_SPIFFS_CMD);
+ Serial.println(HELP_RESTORE_SPIFFS_CMD);
#endif
// GCOVR_EXCL_STOP
Serial.println(HELP_LED_CMD);
@@ -483,6 +484,25 @@ void CommandLine::runCommand(String input) {
Serial.println(F("SD Card NOT Supported"));
#endif
}
+ else if (cmd_args.get(0) == RESTORE_SPIFFS_CMD) {
+ #ifdef HAS_SD
+ size_t files_copied = 0;
+ size_t bytes_copied = 0;
+ String error;
+ if (sd_obj.restoreSPIFFS(files_copied, bytes_copied, error)) {
+ Serial.println("SPIFFS restore complete: " + (String)files_copied +
+ " files, " + (String)bytes_copied + " bytes");
+ Serial.println(F("Restarting to load restored content..."));
+ delay(1000);
+ ESP.restart();
+ }
+ else {
+ Serial.println("SPIFFS restore failed: " + error);
+ }
+ #else
+ Serial.println(F("SD Card NOT Supported"));
+ #endif
+ }
// GCOVR_EXCL_STOP
// Channel command
diff --git a/esp32_marauder/CommandLine.h b/esp32_marauder/CommandLine.h
index dad05b49e..1b2857073 100644
--- a/esp32_marauder/CommandLine.h
+++ b/esp32_marauder/CommandLine.h
@@ -56,6 +56,7 @@ const char PROGMEM HELP_CMD[] = "help";
const char PROGMEM SETTINGS_CMD[] = "settings";
const char PROGMEM LS_CMD[] = "ls";
const char PROGMEM BACKUP_SPIFFS_CMD[] = "backupspiffs";
+const char PROGMEM RESTORE_SPIFFS_CMD[] = "restorespiffs";
const char PROGMEM LED_CMD[] = "led";
const char PROGMEM GPS_DATA_CMD[] = "gpsdata";
const char PROGMEM GPS_CMD[] = "gps";
@@ -135,6 +136,7 @@ const char PROGMEM HELP_UPDATE_CMD_A[] = "update -s/-w";
const char PROGMEM HELP_SETTINGS_CMD[] = "settings [-s enable/disable>]/[-r]";
const char PROGMEM HELP_LS_CMD[] = "ls ";
const char PROGMEM HELP_BACKUP_SPIFFS_CMD[] = "backupspiffs - copy SPIFFS to /spiffs on SD";
+const char PROGMEM HELP_RESTORE_SPIFFS_CMD[] = "restorespiffs - restore SPIFFS from /spiffs on SD";
const char PROGMEM HELP_LED_CMD[] = "led -s /-p ";
const char PROGMEM HELP_GPS_DATA_CMD[] = "gpsdata";
const char PROGMEM HELP_GPS_CMD[] = "gps [-t] [-g] \r\n [-n] \r\n [-b = use BD vs GB for beidou]";
diff --git a/esp32_marauder/MenuFunctions.cpp b/esp32_marauder/MenuFunctions.cpp
index 7b56accc1..59b8b51c6 100644
--- a/esp32_marauder/MenuFunctions.cpp
+++ b/esp32_marauder/MenuFunctions.cpp
@@ -3513,6 +3513,33 @@ void MenuFunctions::RunSetup()
delay(2500);
this->changeMenu(&deviceMenu, true);
});
+
+ this->addNodes(&deviceMenu, "Restore SPIFFS", TFTORANGE, SD_UPDATE, [this]() {
+ display_obj.clearScreen();
+ display_obj.tft.setTextWrap(true);
+ display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
+ display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
+ display_obj.tft.println("Restoring SPIFFS...");
+
+ size_t files_copied = 0;
+ size_t bytes_copied = 0;
+ String error;
+ if (sd_obj.restoreSPIFFS(files_copied, bytes_copied, error)) {
+ display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK);
+ display_obj.tft.println("Restore complete");
+ display_obj.tft.println((String)files_copied + " files");
+ display_obj.tft.println("Restarting...");
+ delay(1500);
+ ESP.restart();
+ }
+ else {
+ display_obj.tft.setTextColor(TFT_RED, TFT_BLACK);
+ display_obj.tft.println("Restore failed");
+ display_obj.tft.println(error);
+ delay(3000);
+ this->changeMenu(&deviceMenu, true);
+ }
+ });
// GCOVR_EXCL_STOP
}
#endif
@@ -4686,4 +4713,3 @@ void MenuFunctions::displayCurrentMenu(int start_index)
#endif
#endif
-
diff --git a/esp32_marauder/SDInterface.cpp b/esp32_marauder/SDInterface.cpp
index 3d977be6f..d35c94dff 100644
--- a/esp32_marauder/SDInterface.cpp
+++ b/esp32_marauder/SDInterface.cpp
@@ -42,6 +42,32 @@ namespace {
return fs.rmdir(path);
}
+ bool clearDirectoryContents(fs::FS& fs, const String& path) {
+ File directory = fs.open(path);
+ if (!directory || !directory.isDirectory()) {
+ directory.close();
+ return false;
+ }
+
+ File child = directory.openNextFile();
+ while (child) {
+ String child_path = child.path();
+ child.close();
+ if (!removeTree(fs, child_path)) {
+ directory.close();
+ return false;
+ }
+ child = directory.openNextFile();
+ }
+
+ directory.close();
+ return true;
+ }
+
+ String joinPath(const String& base, const String& child) {
+ return base == "/" ? "/" + child : base + "/" + child;
+ }
+
bool copyTree(
fs::FS& source,
const String& source_path,
@@ -53,7 +79,7 @@ namespace {
) {
File source_node = source.open(source_path);
if (!source_node) {
- error = "Could not open SPIFFS path " + source_path;
+ error = "Could not open source path " + source_path;
return false;
}
@@ -61,7 +87,7 @@ namespace {
int slash = destination_path.lastIndexOf('/');
if (slash > 0 && !ensureDirectory(destination, destination_path.substring(0, slash))) {
source_node.close();
- error = "Could not create SD backup directory";
+ error = "Could not create destination directory";
return false;
}
@@ -110,7 +136,7 @@ namespace {
source,
child_source_path,
destination,
- destination_path + "/" + child_name,
+ joinPath(destination_path, child_name),
files_copied,
bytes_copied,
error
@@ -274,6 +300,61 @@ bool SDInterface::backupSPIFFS(size_t& files_copied, size_t& bytes_copied, Strin
removeTree(SD, previous_path);
return true;
}
+
+bool SDInterface::restoreSPIFFS(size_t& files_copied, size_t& bytes_copied, String& error) {
+ files_copied = 0;
+ bytes_copied = 0;
+ error = "";
+
+ if (!this->supported) {
+ error = "SD card not detected";
+ return false;
+ }
+
+ const String backup_path = "/spiffs";
+ const String rollback_path = "/spiffs.restore-rollback";
+ File backup = SD.open(backup_path);
+ bool valid_backup = backup && backup.isDirectory();
+ backup.close();
+ if (!valid_backup) {
+ error = "SD:/spiffs backup not found";
+ return false;
+ }
+
+ if (!removeTree(SD, rollback_path)) {
+ error = "Could not clear old restore rollback";
+ return false;
+ }
+
+ size_t rollback_files = 0;
+ size_t rollback_bytes = 0;
+ String rollback_error;
+ if (!copyTree(SPIFFS, "/", SD, rollback_path, rollback_files, rollback_bytes, rollback_error)) {
+ removeTree(SD, rollback_path);
+ error = "Could not preserve current SPIFFS: " + rollback_error;
+ return false;
+ }
+
+ bool cleared = clearDirectoryContents(SPIFFS, "/");
+ if (cleared && copyTree(SD, backup_path, SPIFFS, "/", files_copied, bytes_copied, error)) {
+ removeTree(SD, rollback_path);
+ return true;
+ }
+
+ String restore_error = cleared ? error : "Could not clear SPIFFS before restore";
+ clearDirectoryContents(SPIFFS, "/");
+ size_t recovered_files = 0;
+ size_t recovered_bytes = 0;
+ String recovery_error;
+ if (copyTree(SD, rollback_path, SPIFFS, "/", recovered_files, recovered_bytes, recovery_error)) {
+ removeTree(SD, rollback_path);
+ error = "Restore failed; original SPIFFS recovered: " + restore_error;
+ }
+ else {
+ error = "Restore and rollback failed: " + restore_error + "; " + recovery_error;
+ }
+ return false;
+}
// GCOVR_EXCL_STOP
void SDInterface::listDirToLinkedList(LinkedList* file_names, String str_dir, String ext) {
diff --git a/esp32_marauder/SDInterface.h b/esp32_marauder/SDInterface.h
index 76a5a6a48..1eafd62f5 100644
--- a/esp32_marauder/SDInterface.h
+++ b/esp32_marauder/SDInterface.h
@@ -70,6 +70,7 @@ class SDInterface {
void performUpdate(Stream &updateSource, size_t updateSize);
bool removeFile(String file_path);
bool backupSPIFFS(size_t& files_copied, size_t& bytes_copied, String& error);
+ bool restoreSPIFFS(size_t& files_copied, size_t& bytes_copied, String& error);
};
#endif
From 121019825bccb9cc9deb93b561b8b30124d0386b Mon Sep 17 00:00:00 2001
From: Just Call Me Koko <25190487+justcallmekoko@users.noreply.github.com>
Date: Sat, 22 Aug 2026 21:06:28 -0400
Subject: [PATCH 05/32] Add machine protocol for SPIFFS migration
---
esp32_marauder/CommandLine.cpp | 187 ++++++++++++++++++++++++--
esp32_marauder/CommandLine.h | 8 +-
esp32_marauder/SDInterface.cpp | 56 ++++++++
esp32_marauder/SDInterface.h | 1 +
tools/test_spiffs_machine_protocol.py | 42 ++++++
5 files changed, 283 insertions(+), 11 deletions(-)
create mode 100644 tools/test_spiffs_machine_protocol.py
diff --git a/esp32_marauder/CommandLine.cpp b/esp32_marauder/CommandLine.cpp
index e3b3db02e..f0a85a262 100644
--- a/esp32_marauder/CommandLine.cpp
+++ b/esp32_marauder/CommandLine.cpp
@@ -1,5 +1,79 @@
#include "CommandLine.h"
+// GCOVR_EXCL_START -- serial protocol output depends on Arduino Serial.
+namespace {
+ const int MARAUDER_PROTOCOL_VERSION = 1;
+ const char* MARAUDER_PROTOCOL_PREFIX = "@MARAUDER:";
+
+ String jsonEscape(const String& value) {
+ String escaped;
+ for (size_t i = 0; i < value.length(); i++) {
+ char c = value.charAt(i);
+ if (c == '\\' || c == '"') {
+ escaped += '\\';
+ escaped += c;
+ }
+ else if (c == '\n')
+ escaped += "\\n";
+ else if (c == '\r')
+ escaped += "\\r";
+ else if ((uint8_t)c >= 0x20)
+ escaped += c;
+ }
+ return escaped;
+ }
+
+ bool validTransactionId(const String& transaction_id) {
+ if (transaction_id.length() == 0 || transaction_id.length() > 40)
+ return false;
+
+ for (size_t i = 0; i < transaction_id.length(); i++) {
+ char c = transaction_id.charAt(i);
+ if (!isalnum((unsigned char)c) && c != '-' && c != '_' && c != '.')
+ return false;
+ }
+ return true;
+ }
+
+ void machineResult(
+ const String& transaction_id,
+ const String& command,
+ const String& status,
+ const String& code,
+ size_t files = 0,
+ size_t bytes = 0,
+ bool rebooting = false
+ ) {
+ Serial.print(MARAUDER_PROTOCOL_PREFIX);
+ Serial.print("{\"protocol\":");
+ Serial.print(MARAUDER_PROTOCOL_VERSION);
+ Serial.print(",\"tx\":\"");
+ Serial.print(jsonEscape(transaction_id));
+ Serial.print("\",\"command\":\"");
+ Serial.print(command);
+ Serial.print("\",\"status\":\"");
+ Serial.print(status);
+ Serial.print("\",\"code\":\"");
+ Serial.print(code);
+ Serial.print("\",\"files\":");
+ Serial.print(files);
+ Serial.print(",\"bytes\":");
+ Serial.print(bytes);
+ Serial.print(",\"rebooting\":");
+ Serial.print(rebooting ? "true" : "false");
+ Serial.println("}");
+ }
+
+ String storageErrorCode(const String& error, const String& fallback) {
+ if (error == "SD card not detected")
+ return "SD_NOT_READY";
+ if (error == "SD:/spiffs backup not found")
+ return "BACKUP_NOT_FOUND";
+ return fallback;
+ }
+}
+// GCOVR_EXCL_STOP
+
// Brightness functions defined in esp32_marauder.ino
#ifndef HAS_MINI_SCREEN
extern void brightnessCycle();
@@ -231,9 +305,11 @@ void CommandLine::runCommand(String input) {
Serial.println(HELP_REBOOT_CMD);
Serial.println(HELP_UPDATE_CMD_A);
Serial.println(HELP_LS_CMD);
+ Serial.println(HELP_PROTOCOL_INFO_CMD);
// GCOVR_EXCL_START -- hardware-only command help entry.
#ifdef HAS_SD
Serial.println(HELP_BACKUP_SPIFFS_CMD);
+ Serial.println(HELP_BACKUP_STATUS_CMD);
Serial.println(HELP_RESTORE_SPIFFS_CMD);
#endif
// GCOVR_EXCL_STOP
@@ -468,39 +544,132 @@ void CommandLine::runCommand(String input) {
#endif
}
// GCOVR_EXCL_START -- requires mounted SPIFFS and SD filesystems.
+ else if (cmd_args.get(0) == PROTOCOL_INFO_CMD) {
+ int machine_arg = this->argSearch(&cmd_args, "--machine");
+ String transaction_id = machine_arg >= 0 && machine_arg + 1 < cmd_args.size()
+ ? cmd_args.get(machine_arg + 1) : "";
+ if (machine_arg >= 0 && !validTransactionId(transaction_id))
+ machineResult(transaction_id, PROTOCOL_INFO_CMD, "error", "INVALID_TRANSACTION");
+ else if (machine_arg >= 0) {
+ Serial.print(MARAUDER_PROTOCOL_PREFIX);
+ Serial.print("{\"protocol\":1,\"tx\":\"");
+ Serial.print(jsonEscape(transaction_id));
+ Serial.print("\",\"command\":\"protocolinfo\",\"status\":\"success\",\"code\":\"OK\",\"firmware\":\"");
+ Serial.print(jsonEscape(version_number));
+ Serial.print("\",\"board\":\"");
+ Serial.print(jsonEscape(board_target));
+ #ifdef HAS_SD
+ Serial.println("\",\"capabilities\":[\"spiffs-backup\",\"spiffs-backup-status\",\"spiffs-restore\"],\"backupPath\":\"/spiffs\"}");
+ #else
+ Serial.println("\",\"capabilities\":[]}");
+ #endif
+ }
+ else
+ Serial.println(F("Marauder automation protocol v1: spiffs-backup, spiffs-backup-status, spiffs-restore"));
+ }
else if (cmd_args.get(0) == BACKUP_SPIFFS_CMD) {
+ int machine_arg = this->argSearch(&cmd_args, "--machine");
+ String transaction_id = machine_arg >= 0 && machine_arg + 1 < cmd_args.size()
+ ? cmd_args.get(machine_arg + 1) : "";
+ bool machine = machine_arg >= 0;
+ if (machine && !validTransactionId(transaction_id)) {
+ machineResult(transaction_id, BACKUP_SPIFFS_CMD, "error", "INVALID_TRANSACTION");
+ return;
+ }
#ifdef HAS_SD
size_t files_copied = 0;
size_t bytes_copied = 0;
String error;
+ if (machine)
+ machineResult(transaction_id, BACKUP_SPIFFS_CMD, "started", "OK");
if (sd_obj.backupSPIFFS(files_copied, bytes_copied, error)) {
- Serial.println("SPIFFS backup complete: " + (String)files_copied +
- " files, " + (String)bytes_copied + " bytes -> /spiffs");
+ if (machine)
+ machineResult(transaction_id, BACKUP_SPIFFS_CMD, "success", "OK", files_copied, bytes_copied);
+ else
+ Serial.println("SPIFFS backup complete: " + (String)files_copied +
+ " files, " + (String)bytes_copied + " bytes -> /spiffs");
}
else {
- Serial.println("SPIFFS backup failed: " + error);
+ if (machine)
+ machineResult(transaction_id, BACKUP_SPIFFS_CMD, "error", storageErrorCode(error, "BACKUP_FAILED"));
+ else
+ Serial.println("SPIFFS backup failed: " + error);
}
#else
- Serial.println(F("SD Card NOT Supported"));
+ if (machine)
+ machineResult(transaction_id, BACKUP_SPIFFS_CMD, "error", "SD_NOT_SUPPORTED");
+ else
+ Serial.println(F("SD Card NOT Supported"));
+ #endif
+ }
+ else if (cmd_args.get(0) == BACKUP_STATUS_CMD) {
+ int machine_arg = this->argSearch(&cmd_args, "--machine");
+ String transaction_id = machine_arg >= 0 && machine_arg + 1 < cmd_args.size()
+ ? cmd_args.get(machine_arg + 1) : "";
+ bool machine = machine_arg >= 0;
+ if (machine && !validTransactionId(transaction_id)) {
+ machineResult(transaction_id, BACKUP_STATUS_CMD, "error", "INVALID_TRANSACTION");
+ return;
+ }
+ #ifdef HAS_SD
+ size_t files_found = 0;
+ size_t bytes_found = 0;
+ String error;
+ if (sd_obj.inspectSPIFFSBackup(files_found, bytes_found, error)) {
+ if (machine)
+ machineResult(transaction_id, BACKUP_STATUS_CMD, "success", "OK", files_found, bytes_found);
+ else
+ Serial.println("SPIFFS backup ready: " + (String)files_found +
+ " files, " + (String)bytes_found + " bytes in /spiffs");
+ }
+ else if (machine)
+ machineResult(transaction_id, BACKUP_STATUS_CMD, "error", storageErrorCode(error, "BACKUP_INSPECTION_FAILED"));
+ else
+ Serial.println("SPIFFS backup unavailable: " + error);
+ #else
+ if (machine)
+ machineResult(transaction_id, BACKUP_STATUS_CMD, "error", "SD_NOT_SUPPORTED");
+ else
+ Serial.println(F("SD Card NOT Supported"));
#endif
}
else if (cmd_args.get(0) == RESTORE_SPIFFS_CMD) {
+ int machine_arg = this->argSearch(&cmd_args, "--machine");
+ String transaction_id = machine_arg >= 0 && machine_arg + 1 < cmd_args.size()
+ ? cmd_args.get(machine_arg + 1) : "";
+ bool machine = machine_arg >= 0;
+ if (machine && !validTransactionId(transaction_id)) {
+ machineResult(transaction_id, RESTORE_SPIFFS_CMD, "error", "INVALID_TRANSACTION");
+ return;
+ }
#ifdef HAS_SD
size_t files_copied = 0;
size_t bytes_copied = 0;
String error;
+ if (machine)
+ machineResult(transaction_id, RESTORE_SPIFFS_CMD, "started", "OK");
if (sd_obj.restoreSPIFFS(files_copied, bytes_copied, error)) {
- Serial.println("SPIFFS restore complete: " + (String)files_copied +
- " files, " + (String)bytes_copied + " bytes");
- Serial.println(F("Restarting to load restored content..."));
+ if (machine)
+ machineResult(transaction_id, RESTORE_SPIFFS_CMD, "success", "OK", files_copied, bytes_copied, true);
+ else {
+ Serial.println("SPIFFS restore complete: " + (String)files_copied +
+ " files, " + (String)bytes_copied + " bytes");
+ Serial.println(F("Restarting to load restored content..."));
+ }
delay(1000);
ESP.restart();
}
else {
- Serial.println("SPIFFS restore failed: " + error);
+ if (machine)
+ machineResult(transaction_id, RESTORE_SPIFFS_CMD, "error", storageErrorCode(error, "RESTORE_FAILED"));
+ else
+ Serial.println("SPIFFS restore failed: " + error);
}
#else
- Serial.println(F("SD Card NOT Supported"));
+ if (machine)
+ machineResult(transaction_id, RESTORE_SPIFFS_CMD, "error", "SD_NOT_SUPPORTED");
+ else
+ Serial.println(F("SD Card NOT Supported"));
#endif
}
// GCOVR_EXCL_STOP
diff --git a/esp32_marauder/CommandLine.h b/esp32_marauder/CommandLine.h
index 1b2857073..b695a9f73 100644
--- a/esp32_marauder/CommandLine.h
+++ b/esp32_marauder/CommandLine.h
@@ -55,7 +55,9 @@ const char PROGMEM UPDATE_CMD[] = "update";
const char PROGMEM HELP_CMD[] = "help";
const char PROGMEM SETTINGS_CMD[] = "settings";
const char PROGMEM LS_CMD[] = "ls";
+const char PROGMEM PROTOCOL_INFO_CMD[] = "protocolinfo";
const char PROGMEM BACKUP_SPIFFS_CMD[] = "backupspiffs";
+const char PROGMEM BACKUP_STATUS_CMD[] = "backupstatus";
const char PROGMEM RESTORE_SPIFFS_CMD[] = "restorespiffs";
const char PROGMEM LED_CMD[] = "led";
const char PROGMEM GPS_DATA_CMD[] = "gpsdata";
@@ -135,8 +137,10 @@ const char PROGMEM HELP_REBOOT_CMD[] = "reboot";
const char PROGMEM HELP_UPDATE_CMD_A[] = "update -s/-w";
const char PROGMEM HELP_SETTINGS_CMD[] = "settings [-s enable/disable>]/[-r]";
const char PROGMEM HELP_LS_CMD[] = "ls ";
-const char PROGMEM HELP_BACKUP_SPIFFS_CMD[] = "backupspiffs - copy SPIFFS to /spiffs on SD";
-const char PROGMEM HELP_RESTORE_SPIFFS_CMD[] = "restorespiffs - restore SPIFFS from /spiffs on SD";
+const char PROGMEM HELP_PROTOCOL_INFO_CMD[] = "protocolinfo [--machine ]";
+const char PROGMEM HELP_BACKUP_SPIFFS_CMD[] = "backupspiffs [--machine ] - copy SPIFFS to /spiffs on SD";
+const char PROGMEM HELP_BACKUP_STATUS_CMD[] = "backupstatus [--machine ] - inspect /spiffs on SD";
+const char PROGMEM HELP_RESTORE_SPIFFS_CMD[] = "restorespiffs [--machine ] - restore SPIFFS from /spiffs on SD";
const char PROGMEM HELP_LED_CMD[] = "led -s /-p ";
const char PROGMEM HELP_GPS_DATA_CMD[] = "gpsdata";
const char PROGMEM HELP_GPS_CMD[] = "gps [-t] [-g] \r\n [-n] \r\n [-b = use BD vs GB for beidou]";
diff --git a/esp32_marauder/SDInterface.cpp b/esp32_marauder/SDInterface.cpp
index d35c94dff..caf8cad2a 100644
--- a/esp32_marauder/SDInterface.cpp
+++ b/esp32_marauder/SDInterface.cpp
@@ -150,6 +150,41 @@ namespace {
source_node.close();
return true;
}
+
+ bool measureTree(
+ fs::FS& fs,
+ const String& path,
+ size_t& files_found,
+ size_t& bytes_found,
+ String& error
+ ) {
+ File node = fs.open(path);
+ if (!node) {
+ error = "Could not open backup path " + path;
+ return false;
+ }
+
+ if (!node.isDirectory()) {
+ bytes_found += node.size();
+ files_found++;
+ node.close();
+ return true;
+ }
+
+ File child = node.openNextFile();
+ while (child) {
+ String child_path = child.path();
+ child.close();
+ if (!measureTree(fs, child_path, files_found, bytes_found, error)) {
+ node.close();
+ return false;
+ }
+ child = node.openNextFile();
+ }
+
+ node.close();
+ return true;
+ }
}
// GCOVR_EXCL_STOP
@@ -301,6 +336,27 @@ bool SDInterface::backupSPIFFS(size_t& files_copied, size_t& bytes_copied, Strin
return true;
}
+bool SDInterface::inspectSPIFFSBackup(size_t& files_found, size_t& bytes_found, String& error) {
+ files_found = 0;
+ bytes_found = 0;
+ error = "";
+
+ if (!this->supported) {
+ error = "SD card not detected";
+ return false;
+ }
+
+ File backup = SD.open("/spiffs");
+ bool valid_backup = backup && backup.isDirectory();
+ backup.close();
+ if (!valid_backup) {
+ error = "SD:/spiffs backup not found";
+ return false;
+ }
+
+ return measureTree(SD, "/spiffs", files_found, bytes_found, error);
+}
+
bool SDInterface::restoreSPIFFS(size_t& files_copied, size_t& bytes_copied, String& error) {
files_copied = 0;
bytes_copied = 0;
diff --git a/esp32_marauder/SDInterface.h b/esp32_marauder/SDInterface.h
index 1eafd62f5..07a93c314 100644
--- a/esp32_marauder/SDInterface.h
+++ b/esp32_marauder/SDInterface.h
@@ -70,6 +70,7 @@ class SDInterface {
void performUpdate(Stream &updateSource, size_t updateSize);
bool removeFile(String file_path);
bool backupSPIFFS(size_t& files_copied, size_t& bytes_copied, String& error);
+ bool inspectSPIFFSBackup(size_t& files_found, size_t& bytes_found, String& error);
bool restoreSPIFFS(size_t& files_copied, size_t& bytes_copied, String& error);
};
diff --git a/tools/test_spiffs_machine_protocol.py b/tools/test_spiffs_machine_protocol.py
new file mode 100644
index 000000000..ace9f3de4
--- /dev/null
+++ b/tools/test_spiffs_machine_protocol.py
@@ -0,0 +1,42 @@
+import re
+import unittest
+from pathlib import Path
+
+
+ROOT = Path(__file__).resolve().parents[1]
+
+
+class SpiffsMachineProtocolTests(unittest.TestCase):
+ def test_protocol_is_versioned_framed_and_transactional(self):
+ header = (ROOT / "esp32_marauder" / "CommandLine.h").read_text()
+ source = (ROOT / "esp32_marauder" / "CommandLine.cpp").read_text()
+
+ self.assertIn('PROTOCOL_INFO_CMD[] = "protocolinfo"', header)
+ self.assertIn('BACKUP_STATUS_CMD[] = "backupstatus"', header)
+ self.assertIn('MARAUDER_PROTOCOL_PREFIX = "@MARAUDER:"', source)
+ self.assertIn("MARAUDER_PROTOCOL_VERSION = 1", source)
+ self.assertIn('this->argSearch(&cmd_args, "--machine")', source)
+ self.assertIn('"INVALID_TRANSACTION"', source)
+ self.assertIn('"SD_NOT_SUPPORTED"', source)
+ self.assertRegex(source, r'machineResult\([^;]+"started"')
+ self.assertRegex(source, r'machineResult\([^;]+"success"')
+
+ def test_machine_restore_acknowledges_reboot(self):
+ source = (ROOT / "esp32_marauder" / "CommandLine.cpp").read_text()
+ restore = source[source.index("else if (cmd_args.get(0) == RESTORE_SPIFFS_CMD)") :]
+ success = restore.index('machineResult(transaction_id, RESTORE_SPIFFS_CMD, "success"')
+ restart = restore.index("ESP.restart();")
+ self.assertLess(success, restart)
+ self.assertIn("files_copied, bytes_copied, true", restore[success:restart])
+
+ def test_backup_status_measures_the_activated_backup(self):
+ source = (ROOT / "esp32_marauder" / "SDInterface.cpp").read_text()
+ method = re.search(
+ r"bool SDInterface::inspectSPIFFSBackup\(.*?\n\}", source, re.S
+ ).group(0)
+ self.assertIn('SD.open("/spiffs")', method)
+ self.assertIn('measureTree(SD, "/spiffs"', method)
+
+
+if __name__ == "__main__":
+ unittest.main()
From cd7d91264e859e2c97f28fa4589428225ead40db Mon Sep 17 00:00:00 2001
From: Just Call Me Koko <25190487+justcallmekoko@users.noreply.github.com>
Date: Sat, 22 Aug 2026 21:14:28 -0400
Subject: [PATCH 06/32] Avoid undefined board identity in protocol response
---
esp32_marauder/CommandLine.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/esp32_marauder/CommandLine.cpp b/esp32_marauder/CommandLine.cpp
index f0a85a262..3e4e77fbc 100644
--- a/esp32_marauder/CommandLine.cpp
+++ b/esp32_marauder/CommandLine.cpp
@@ -556,8 +556,6 @@ void CommandLine::runCommand(String input) {
Serial.print(jsonEscape(transaction_id));
Serial.print("\",\"command\":\"protocolinfo\",\"status\":\"success\",\"code\":\"OK\",\"firmware\":\"");
Serial.print(jsonEscape(version_number));
- Serial.print("\",\"board\":\"");
- Serial.print(jsonEscape(board_target));
#ifdef HAS_SD
Serial.println("\",\"capabilities\":[\"spiffs-backup\",\"spiffs-backup-status\",\"spiffs-restore\"],\"backupPath\":\"/spiffs\"}");
#else
From 8df054b29e3f2293055ce8d4de850ee105ca9430 Mon Sep 17 00:00:00 2001
From: Just Call Me Koko <25190487+justcallmekoko@users.noreply.github.com>
Date: Sat, 22 Aug 2026 21:23:14 -0400
Subject: [PATCH 07/32] Exclude serial help from native coverage
---
esp32_marauder/CommandLine.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/esp32_marauder/CommandLine.cpp b/esp32_marauder/CommandLine.cpp
index 3e4e77fbc..db06f7fed 100644
--- a/esp32_marauder/CommandLine.cpp
+++ b/esp32_marauder/CommandLine.cpp
@@ -305,8 +305,8 @@ void CommandLine::runCommand(String input) {
Serial.println(HELP_REBOOT_CMD);
Serial.println(HELP_UPDATE_CMD_A);
Serial.println(HELP_LS_CMD);
- Serial.println(HELP_PROTOCOL_INFO_CMD);
// GCOVR_EXCL_START -- hardware-only command help entry.
+ Serial.println(HELP_PROTOCOL_INFO_CMD);
#ifdef HAS_SD
Serial.println(HELP_BACKUP_SPIFFS_CMD);
Serial.println(HELP_BACKUP_STATUS_CMD);
From 8076b2fd2e89a1b4917bc969e37f5d783d066281 Mon Sep 17 00:00:00 2001
From: Just Call Me Koko <25190487+justcallmekoko@users.noreply.github.com>
Date: Sun, 23 Aug 2026 17:07:14 -0400
Subject: [PATCH 08/32] Revert "Promote v1.15.1 changes to master (#1492)"
This reverts commit ea234f4a1c88c318eb4afc210d95deb822a034f9, reversing
changes made to 6e375e377abb70084720484e9b25de485627f688.
---
.github/workflows/build_parallel.yml | 2 +-
.github/workflows/nightly_build.yml | 2 +-
esp32_marauder/CommandLine.cpp | 10 +-
esp32_marauder/IPv4Range.cpp | 43 -
esp32_marauder/IPv4Range.h | 20 -
esp32_marauder/MenuFunctions.cpp | 8818 +++++++++++++-------------
esp32_marauder/WiFiScan.cpp | 270 +-
esp32_marauder/WiFiScan.h | 18 +-
esp32_marauder/configs.h | 2 +-
esp32_marauder/utils.h | 70 +-
platformio.ini | 1 -
test/test_ipv4_range/test_main.cpp | 86 -
tools/test_installer_manifest.py | 3 -
13 files changed, 4559 insertions(+), 4786 deletions(-)
delete mode 100644 esp32_marauder/IPv4Range.cpp
delete mode 100644 esp32_marauder/IPv4Range.h
delete mode 100644 test/test_ipv4_range/test_main.cpp
diff --git a/.github/workflows/build_parallel.yml b/.github/workflows/build_parallel.yml
index 771275dfd..6e1b4d135 100644
--- a/.github/workflows/build_parallel.yml
+++ b/.github/workflows/build_parallel.yml
@@ -36,7 +36,7 @@ jobs:
- { name: "Marauder CYD 3.5inch", flag: "MARAUDER_CYD_3_5_INCH", fbqn: "esp32:esp32:d32:PartitionScheme=min_spiffs", file_name: "cyd_3_5_inch", tft: true, tft_file: "User_Setup_cyd_3_5_inch.h", build_dir: "d32", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" }
- { name: "M5Cardputer", flag: "MARAUDER_CARDPUTER", fbqn: "esp32:esp32:esp32s3:PartitionScheme=min_spiffs,FlashSize=8M,PSRAM=disabled", file_name: "m5cardputer", tft: true, tft_file: "User_Setup_marauder_m5cardputer.h", build_dir: "esp32s3", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" }
- { name: "M5Cardputer ADV", flag: "MARAUDER_CARDPUTER_ADV", fbqn: "esp32:esp32:esp32s3:PartitionScheme=min_spiffs,FlashSize=8M,PSRAM=disabled", file_name: "m5cardputer_adv", tft: true, tft_file: "User_Setup_marauder_m5cardputer_adv.h", build_dir: "esp32s3", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" }
- - { name: "ESP32-C5-DevKitC-1", flag: "MARAUDER_C5", fbqn: "esp32:esp32:esp32c5:FlashSize=8M,PartitionScheme=default_8MB,PSRAM=enabled", file_name: "esp32c5devkitc1", tft: false, tft_file: "", build_dir: "esp32c5", addr: "0x2000", idf_ver: "3.3.4", nimble_ver: "2.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" }
+ - { name: "ESP32-C5-DevKitC-1", flag: "MARAUDER_C5", fbqn: "esp32:esp32:esp32c5:FlashSize=8M,PartitionScheme=min_spiffs,PSRAM=enabled", file_name: "esp32c5devkitc1", tft: false, tft_file: "", build_dir: "esp32c5", addr: "0x2000", idf_ver: "3.3.4", nimble_ver: "2.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" }
- { name: "LilyGo T-Dongle C5", flag: "MARAUDER_T_DONGLE_C5", fbqn: "esp32:esp32:esp32c5:CDCOnBoot=cdc,FlashMode=qio,FlashSize=16M,PartitionScheme=custom,PSRAM=enabled", file_name: "t_dongle_c5", tft: true, tft_file: "User_Setup_marauder_t_dongle_c5.h", tft_repo: "H4W9/TFT_eSPI", tft_ref: "ESP32-C5", build_dir: "esp32c5", addr: "0x2000", idf_ver: "3.3.4", nimble_ver: "2.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" }
- { name: "M5NanoC6", flag: "MARAUDER_M5_NANO_C6", fbqn: "esp32:esp32:esp32c6:CDCOnBoot=cdc,PartitionScheme=min_spiffs", file_name: "m5nanoc6", tft: false, tft_file: "", build_dir: "esp32c6", addr: "0x2000", idf_ver: "3.3.4", nimble_ver: "2.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" }
- { name: "Marauder Pancake", flag: "MARAUDER_PANCAKE", fbqn: "esp32:esp32:esp32c5:FlashSize=8M,PartitionScheme=default_8MB,PSRAM=enabled", file_name: "pancake", tft: true, tft_file: "User_Setup_marauder_pancake.h", build_dir: "esp32c5", addr: "0x2000", idf_ver: "3.3.4", nimble_ver: "2.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master", tft_repo: "H4W9/TFT_eSPI", tft_ref: "ESP32-C5" }
diff --git a/.github/workflows/nightly_build.yml b/.github/workflows/nightly_build.yml
index 4eb462e46..50318e33f 100644
--- a/.github/workflows/nightly_build.yml
+++ b/.github/workflows/nightly_build.yml
@@ -99,7 +99,7 @@ jobs:
- { name: "Marauder CYD 3.5inch", flag: "MARAUDER_CYD_3_5_INCH", fbqn: "esp32:esp32:d32:PartitionScheme=min_spiffs", file_name: "cyd_3_5_inch", tft: true, tft_file: "User_Setup_cyd_3_5_inch.h", build_dir: "d32", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" }
- { name: "M5Cardputer", flag: "MARAUDER_CARDPUTER", fbqn: "esp32:esp32:esp32s3:PartitionScheme=min_spiffs,FlashSize=8M,PSRAM=disabled", file_name: "m5cardputer", tft: true, tft_file: "User_Setup_marauder_m5cardputer.h", build_dir: "esp32s3", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" }
- { name: "M5Cardputer ADV", flag: "MARAUDER_CARDPUTER_ADV", fbqn: "esp32:esp32:esp32s3:PartitionScheme=min_spiffs,FlashSize=8M,PSRAM=disabled", file_name: "m5cardputer_adv", tft: true, tft_file: "User_Setup_marauder_m5cardputer_adv.h", build_dir: "esp32s3", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" }
- - { name: "ESP32-C5-DevKitC-1", flag: "MARAUDER_C5", fbqn: "esp32:esp32:esp32c5:FlashSize=8M,PartitionScheme=default_8MB,PSRAM=enabled", file_name: "esp32c5devkitc1", tft: false, tft_file: "", build_dir: "esp32c5", addr: "0x2000", idf_ver: "3.3.4", nimble_ver: "2.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" }
+ - { name: "ESP32-C5-DevKitC-1", flag: "MARAUDER_C5", fbqn: "esp32:esp32:esp32c5:FlashSize=8M,PartitionScheme=min_spiffs,PSRAM=enabled", file_name: "esp32c5devkitc1", tft: false, tft_file: "", build_dir: "esp32c5", addr: "0x2000", idf_ver: "3.3.4", nimble_ver: "2.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" }
- { name: "LilyGo T-Dongle C5", flag: "MARAUDER_T_DONGLE_C5", fbqn: "esp32:esp32:esp32c5:CDCOnBoot=cdc,FlashMode=qio,FlashSize=16M,PartitionScheme=custom,PSRAM=enabled", file_name: "t_dongle_c5", tft: true, tft_file: "User_Setup_marauder_t_dongle_c5.h", tft_repo: "H4W9/TFT_eSPI", tft_ref: "ESP32-C5", build_dir: "esp32c5", addr: "0x2000", idf_ver: "3.3.4", nimble_ver: "2.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" }
- { name: "M5NanoC6", flag: "MARAUDER_M5_NANO_C6", fbqn: "esp32:esp32:esp32c6:CDCOnBoot=cdc,PartitionScheme=min_spiffs", file_name: "m5nanoc6", tft: false, tft_file: "", build_dir: "esp32c6", addr: "0x2000", idf_ver: "3.3.4", nimble_ver: "2.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" }
diff --git a/esp32_marauder/CommandLine.cpp b/esp32_marauder/CommandLine.cpp
index 30a242829..429829c46 100644
--- a/esp32_marauder/CommandLine.cpp
+++ b/esp32_marauder/CommandLine.cpp
@@ -1289,11 +1289,11 @@ void CommandLine::runCommand(String input) {
this->startScanFromCLI(WIFI_PING_SCAN, TFT_GREEN, "Ping Scan");
}
- // GCOVR_EXCL_START -- command dispatch requires the firmware CLI runtime.
- if (cmd_args.get(0) == ARP_SCAN_CMD) {
- this->startScanFromCLI(WIFI_ARP_SCAN, TFT_CYAN, "ARP Scan");
- }
- // GCOVR_EXCL_STOP
+ #ifndef HAS_DUAL_BAND
+ if (cmd_args.get(0) == ARP_SCAN_CMD) {
+ this->startScanFromCLI(WIFI_ARP_SCAN, TFT_CYAN, "ARP Scan");
+ }
+ #endif
// GPS POI
if (cmd_args.get(0) == GPS_POI_CMD) {
diff --git a/esp32_marauder/IPv4Range.cpp b/esp32_marauder/IPv4Range.cpp
deleted file mode 100644
index 5e9c7cfef..000000000
--- a/esp32_marauder/IPv4Range.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-#include "IPv4Range.h"
-
-namespace marauder {
-
-namespace {
-
-bool isContiguousMask(uint32_t mask) {
- const uint32_t inverted = ~mask;
- return (inverted & (inverted + 1U)) == 0U;
-}
-
-} // namespace
-
-IPv4HostRange ipv4HostRange(uint32_t address, uint32_t subnetMask) {
- const uint32_t network = address & subnetMask;
- const uint32_t broadcast = network | ~subnetMask;
- const bool valid = isContiguousMask(subnetMask) &&
- (broadcast - network) >= 2U;
-
- return {network, broadcast, valid ? network + 1U : 0U,
- valid ? broadcast - 1U : 0U, valid};
-}
-
-uint32_t nextIPv4Host(uint32_t current, const IPv4HostRange& range) {
- if (!range.valid || current >= range.last) {
- return 0U;
- }
- if (current < range.first) {
- return range.first;
- }
- return current + 1U;
-}
-
-uint32_t previousIPv4Host(uint32_t current, uint32_t steps,
- const IPv4HostRange& range) {
- if (!range.valid || current < range.first || current > range.last ||
- steps > current - range.first) {
- return 0U;
- }
- return current - steps;
-}
-
-} // namespace marauder
diff --git a/esp32_marauder/IPv4Range.h b/esp32_marauder/IPv4Range.h
deleted file mode 100644
index 5049c765e..000000000
--- a/esp32_marauder/IPv4Range.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#pragma once
-
-#include
-
-namespace marauder {
-
-struct IPv4HostRange {
- uint32_t network;
- uint32_t broadcast;
- uint32_t first;
- uint32_t last;
- bool valid;
-};
-
-IPv4HostRange ipv4HostRange(uint32_t address, uint32_t subnetMask);
-uint32_t nextIPv4Host(uint32_t current, const IPv4HostRange& range);
-uint32_t previousIPv4Host(uint32_t current, uint32_t steps,
- const IPv4HostRange& range);
-
-} // namespace marauder
diff --git a/esp32_marauder/MenuFunctions.cpp b/esp32_marauder/MenuFunctions.cpp
index 4a9087f64..9a0d830fe 100644
--- a/esp32_marauder/MenuFunctions.cpp
+++ b/esp32_marauder/MenuFunctions.cpp
@@ -1,1549 +1,1549 @@
-#include "MenuFunctions.h"
-#include "lang_var.h"
-
-#ifdef HAS_SCREEN
-
+#include "MenuFunctions.h"
+#include "lang_var.h"
+
+#ifdef HAS_SCREEN
+
extern const unsigned char menu_icons[][66];
extern LinkedList* access_points;
extern LinkedList* stations;
extern LinkedList* airtags;
extern LinkedList* flippers;
extern LinkedList* ble_devices;
-
-#ifdef HAS_MINI_SCREEN
-void MenuFunctions::drawMiniMenuButton(int b, int x, bool selected) {
- if (!current_menu || !current_menu->list || x < 0 || x >= current_menu->list->size())
- return;
-
- MenuNode mini_node = current_menu->list->get(x);
- bool is_setting_node = (mini_node.icon == SETTINGS && mini_node.color == TFTLIGHTGREY);
- uint16_t color = is_setting_node ? (mini_node.selected ? TFT_GREEN : TFT_RED) : this->getColor(mini_node.color);
- int16_t button_x = KEY_X - (KEY_W / 2);
- int16_t button_y = (KEY_Y + (b * (KEY_H + KEY_SPACING_Y))) - (KEY_H / 2);
-
- uint16_t background = selected ? (is_setting_node ? TFT_LIGHTGREY : color) : TFT_BLACK;
- uint16_t text_color = (selected && !is_setting_node) ? TFT_BLACK : color;
-
- display_obj.tft.setFreeFont(NULL);
- display_obj.tft.setTextSize(1);
- display_obj.tft.setTextWrap(false);
- display_obj.tft.fillRect(button_x, button_y - 4, KEY_W, KEY_H, background);
- display_obj.tft.setTextColor(text_color, background);
- display_obj.tft.setCursor(button_x + BUTTON_PADDING, button_y + (KEY_H / 2) - 8);
- display_obj.tft.print(current_menu->list->get(x).name);
-}
-#endif
-
-void MenuFunctions::buttonNotSelected(int b, int x) {
- if (x == -1)
- x = b;
-
- // Ensure b is within valid button index range
- b = (x - menu_start_index) % BUTTON_SCREEN_LIMIT;
-
- #ifdef HAS_MINI_SCREEN
- this->drawMiniMenuButton(b, x, false);
- #endif
-
- uint16_t color = (current_menu->list->get(x).icon == SETTINGS && current_menu->list->get(x).color == TFTLIGHTGREY) ? (current_menu->list->get(x).selected ? TFT_GREEN : TFT_RED) : this->getColor(current_menu->list->get(x).color);
- uint16_t icon_color = (current_menu->list->get(x).icon == SETTINGS && current_menu->list->get(x).color == TFTLIGHTGREY) ? TFT_LIGHTGREY : color;
-
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.setFreeFont(MENU_FONT);
- display_obj.key[b].initButton(&display_obj.tft, KEY_X, KEY_Y + b * (KEY_H + KEY_SPACING_Y), KEY_W, KEY_H, TFT_BLACK, TFT_BLACK, color, (char*)"", KEY_TEXTSIZE);
- display_obj.key[b].drawButton(false, current_menu->list->get(x).name);
- if ((current_menu->list->get(x).name != text09) && (current_menu->list->get(x).icon != 255))
- display_obj.tft.drawXBitmap(0,
- KEY_Y + (b * (KEY_H + KEY_SPACING_Y)) - (ICON_H / 2),
- menu_icons[current_menu->list->get(x).icon],
- ICON_W,
- ICON_H,
- TFT_BLACK,
- icon_color);
- display_obj.tft.setFreeFont(NULL);
- #endif
-}
-
-void MenuFunctions::buttonSelected(int b, int x) {
- if (x == -1)
- x = b;
-
- // Ensure b is within valid button index range
- b = (x - menu_start_index) % BUTTON_SCREEN_LIMIT;
-
- uint16_t color = this->getColor(current_menu->list->get(x).color);
-
- #ifdef HAS_MINI_SCREEN
- this->drawMiniMenuButton(b, x, true);
- #endif
-
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.setFreeFont(MENU_FONT);
- if (current_menu->list->get(x).icon == SETTINGS && current_menu->list->get(x).color == TFTLIGHTGREY) {
- uint16_t setting_color = current_menu->list->get(x).selected ? TFT_GREEN : TFT_RED;
- display_obj.key[b].initButton(&display_obj.tft, KEY_X, KEY_Y + b * (KEY_H + KEY_SPACING_Y), KEY_W, KEY_H, TFT_BLACK, TFT_LIGHTGREY, setting_color, (char*)"", KEY_TEXTSIZE);
- display_obj.key[b].drawButton(false, current_menu->list->get(x).name);
- display_obj.tft.drawXBitmap(0,
- KEY_Y + (b * (KEY_H + KEY_SPACING_Y)) - (ICON_H / 2),
- menu_icons[current_menu->list->get(x).icon],
- ICON_W,
- ICON_H,
- TFT_BLACK,
- TFT_LIGHTGREY);
- } else {
- display_obj.key[b].drawButton(true, current_menu->list->get(x).name);
- if ((current_menu->list->get(x).name != text09) && (current_menu->list->get(x).icon != 255))
- display_obj.tft.drawXBitmap(0,
- KEY_Y + (b * (KEY_H + KEY_SPACING_Y)) - (ICON_H / 2),
- menu_icons[current_menu->list->get(x).icon],
- ICON_W,
- ICON_H,
- TFT_BLACK,
- color);
- }
- display_obj.tft.setFreeFont(NULL);
- #endif
-}
-
-void MenuFunctions::displayMenuButtons() {
- #ifdef HAS_ILI9341
- // Draw lines to show each menu button
- for (int i = 0; i < 3; i++) {
-
- // Draw horizontal line on left
- display_obj.tft.drawLine(0,
- TFT_HEIGHT / 3 * (i),
- (TFT_WIDTH / 12) / 2,
- TFT_HEIGHT / 3 * (i),
- TFT_FARTGRAY);
-
- // Draw horizontal line on right
- display_obj.tft.drawLine(TFT_WIDTH - 1 - ((TFT_WIDTH / 12) / 2),
- TFT_HEIGHT / 3 * (i),
- TFT_WIDTH,
- TFT_HEIGHT / 3 * (i),
- TFT_FARTGRAY);
-
- // Draw vertical line on left
- display_obj.tft.drawLine(0,
- (TFT_HEIGHT / 3 * (i)) - ((TFT_WIDTH / 12) / 2),
- 0,
- (TFT_HEIGHT / 3 * (i)) + ((TFT_WIDTH / 12) / 2),
- TFT_FARTGRAY);
-
- // Draw vertical line on right
- display_obj.tft.drawLine(TFT_WIDTH - 1,
- (TFT_HEIGHT / 3 * (i)) - ((TFT_WIDTH / 12) / 2),
- TFT_WIDTH - 1,
- (TFT_HEIGHT / 3 * (i)) + ((TFT_WIDTH / 12) / 2),
- TFT_FARTGRAY);
- }
- #endif
-}
-
-// Function to check menu input
-void MenuFunctions::main(uint32_t currentTime)
-{
- #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
- this->updateKeyboard();
- #endif
-
- // Some function exited and we need to go back to normal
- if (display_obj.exit_draw) {
- if (wifi_scan_obj.currentScanMode != WIFI_CONNECTED)
- wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF;
- display_obj.exit_draw = false;
- this->orientDisplay();
- }
- if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
- (wifi_scan_obj.currentScanMode == WIFI_CONNECTED) ||
- (wifi_scan_obj.currentScanMode == OTA_UPDATE) ||
- (wifi_scan_obj.currentScanMode == ESP_UPDATE) ||
- (wifi_scan_obj.currentScanMode == SHOW_INFO) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_GPS_DATA) ||
- (wifi_scan_obj.currentScanMode == GPS_POI) ||
- (wifi_scan_obj.currentScanMode == GPS_TRACKER) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_GPS_NMEA)) {
- if (wifi_scan_obj.orient_display) {
- this->orientDisplay();
- wifi_scan_obj.orient_display = false;
- }
- }
-
- if (currentTime != 0) {
- if (currentTime - initTime >= BANNER_TIME) {
- this->initTime = millis();
- if ((wifi_scan_obj.currentScanMode != LV_JOIN_WIFI) &&
- (wifi_scan_obj.currentScanMode != LV_ADD_SSID))
- this->updateStatusBar();
-
- // Do channel analyzer stuff
- if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_ANALYZER)){
- #ifdef HAS_SCREEN
- this->setGraphScale(this->graphScaleCheck(wifi_scan_obj._analyzer_values));
-
- this->drawGraph(wifi_scan_obj._analyzer_values);
- #endif
- }
-
- if (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) {
- #ifdef HAS_SCREEN
- this->setGraphScale(this->graphScaleCheckSmall(wifi_scan_obj.channel_activity));
-
- this->drawGraphSmall(wifi_scan_obj.channel_activity);
-
- #endif
- }
- }
- }
-
-
- boolean pressed = false;
- // This is code from bodmer's keypad example
- uint16_t t_x = 0, t_y = 0; // To store the touch coordinates
-
- // Get the display buffer out of the way
- if ((wifi_scan_obj.currentScanMode != WIFI_SCAN_OFF ) &&
- (wifi_scan_obj.currentScanMode != WIFI_CONNECTED) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_BEACON_SPAM) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_AP_SPAM) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_CSA) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_QUIET) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_AUTH) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH_MANUAL) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH_TARGETED) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_BAD_MSG_TARGETED) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_BAD_MSG) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_SLEEP) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_SLEEP_TARGETED) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_MIMIC) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_FUNNY_BEACON) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_RICK_ROLL))
- display_obj.displayBuffer();
-
-
- int pre_getTouch = millis();
-
- #ifdef HAS_ILI9341
- if (!this->disable_touch)
- pressed = display_obj.updateTouch(&t_x, &t_y);
- #endif
-
-
- // Brightness gesture: hold top or bottom zone 1.5s to enter brightness mode
- #ifdef HAS_ILI9341
- if (pressed && (wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF ||
- wifi_scan_obj.currentScanMode == WIFI_CONNECTED)) {
- uint16_t zoneUp = TFT_HEIGHT * 25 / 100;
- uint16_t zoneDown = TFT_HEIGHT * 75 / 100;
- if (t_y < zoneUp || t_y >= zoneDown) {
- uint32_t hold_start = millis();
- uint16_t hx, hy;
- bool held = false;
- while (display_obj.updateTouch(&hx, &hy)) {
- if (millis() - hold_start >= 1500) {
- held = true;
- break;
- }
- delay(10);
- }
- if (held) {
- // Wait for release before entering brightness mode
- while (display_obj.updateTouch(&hx, &hy)) delay(10);
- this->brightnessMode();
- return;
- }
- }
- }
- #endif
-
- // POI button interception during wardrive — full width bottom bar
- #ifdef HAS_ILI9341
- if (pressed &&
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_WAR_DRIVE ||
- wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION_WAR_DRIVE)) {
- if (t_y >= (SCREEN_HEIGHT - 50)) {
- wifi_scan_obj.tagPOI(nullptr);
- // Brief green flash
- display_obj.tft.fillRect(0, SCREEN_HEIGHT - 50, SCREEN_WIDTH, 50, TFT_GREEN);
- display_obj.tft.setTextSize(2);
- #ifdef HAS_GPS
- if (gps_obj.getFixStatus())
- display_obj.tft.setTextColor(TFT_BLACK, TFT_GREEN);
- else
- #endif
- display_obj.tft.setTextColor(TFT_BLACK, TFT_RED);
- String poiFlash = "POI (" + String(wifi_scan_obj.poiCount) + ")";
- int16_t flashWidth = poiFlash.length() * 12;
- display_obj.tft.setCursor((SCREEN_WIDTH - flashWidth) / 2, SCREEN_HEIGHT - 33);
- display_obj.tft.print(poiFlash);
- delay(200);
- x = -1;
- y = -1;
- return;
- }
- }
- #endif
-
- // This is if there are scans/attacks going on
- #ifdef HAS_ILI9341
- if ((wifi_scan_obj.currentScanMode != WIFI_SCAN_OFF) &&
- (pressed) &&
- (wifi_scan_obj.currentScanMode != WIFI_CONNECTED) &&
- (wifi_scan_obj.currentScanMode != OTA_UPDATE) &&
- (wifi_scan_obj.currentScanMode != ESP_UPDATE) &&
- (wifi_scan_obj.currentScanMode != SHOW_INFO) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_GPS_DATA) &&
- (wifi_scan_obj.currentScanMode != GPS_POI) &&
- (wifi_scan_obj.currentScanMode != GPS_TRACKER) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_GPS_NMEA))
- {
- // Stop the current scan
- if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_SAE_COMMIT) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_DETECT_FOLLOW) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION_WAR_DRIVE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_WAR_DRIVE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_DISPLAY_AP_INFO) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_EVIL_PORTAL) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP_STA) ||
- (wifi_scan_obj.currentScanMode == WIFI_PING_SCAN) ||
- (wifi_scan_obj.currentScanMode == WIFI_ARP_SCAN) ||
- (wifi_scan_obj.currentScanMode == WIFI_PORT_SCAN_ALL) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_SSH) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_TELNET) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_DNS) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_SMTP) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_HTTP) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_HTTPS) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_RDP) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PWN) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PINESCAN) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_MULTISSID) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_ESPRESSIF) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_ALL) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BEACON_SPAM) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_AP_SPAM) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_CSA) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_QUIET) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_AUTH) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH_MANUAL) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH_TARGETED) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BAD_MSG_TARGETED) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BAD_MSG) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SLEEP) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SLEEP_TARGETED) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SAE_COMMIT) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_MIMIC) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_FUNNY_BEACON) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_RICK_ROLL) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BEACON_LIST) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_ALL) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_FOX_HUNT) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_FINDMY_LIVE) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_RAYBAN) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG_MON) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_FLIPPER) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_SIMPLE) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_SIMPLE_TWO) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_SOUR_APPLE) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_APPLE_JUICE) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_SWIFTPAIR_SPAM) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_SPAM_ALL) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_SAMSUNG_SPAM) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_GOOGLE_SPAM) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_FLIPPER_SPAM) ||
- (wifi_scan_obj.currentScanMode == BT_SPOOF_AIRTAG) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_WAR_DRIVE) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_WAR_DRIVE_CONT) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_SKIMMERS) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_ANALYZER))
- {
- wifi_scan_obj.StartScan(WIFI_SCAN_OFF);
-
- // If we don't do this, the text and button coordinates will be off
- display_obj.init();
-
- // Take us back to the menu
- changeMenu(current_menu, true);
- }
-
- x = -1;
- y = -1;
-
- return;
- }
- #endif
-
- #ifdef HAS_BUTTONS
-
- #if (C_BTN >= 0) && !defined(MARAUDER_CARDPUTER) && !defined(MARAUDER_CARDPUTER_ADV)
- bool c_btn_press = c_btn.justPressed();
- #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
- bool c_btn_press = this->isKeyPressed('(');
- #endif
-
- #ifndef HAS_ILI9341
-
- if ((c_btn_press) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_OFF) &&
- (wifi_scan_obj.currentScanMode != WIFI_CONNECTED) &&
- (wifi_scan_obj.currentScanMode != OTA_UPDATE) &&
- (wifi_scan_obj.currentScanMode != ESP_UPDATE) &&
- (wifi_scan_obj.currentScanMode != SHOW_INFO) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_GPS_DATA) &&
- (wifi_scan_obj.currentScanMode != GPS_POI) &&
- (wifi_scan_obj.currentScanMode != GPS_TRACKER) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_GPS_NMEA))
- {
- // Stop the current scan
- if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_SAE_COMMIT) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_DETECT_FOLLOW) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION_WAR_DRIVE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_RAW_CAPTURE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_WAR_DRIVE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_DISPLAY_AP_INFO) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_EVIL_PORTAL) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_FINDMY_LIVE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP_STA) ||
- (wifi_scan_obj.currentScanMode == WIFI_PING_SCAN) ||
- (wifi_scan_obj.currentScanMode == WIFI_ARP_SCAN) ||
- (wifi_scan_obj.currentScanMode == WIFI_PORT_SCAN_ALL) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_SSH) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_TELNET) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_DNS) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_SMTP) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_HTTP) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_HTTPS) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_RDP) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PWN) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PINESCAN) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_MULTISSID) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_ESPRESSIF) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_ALL) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_DEAUTH) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BEACON_SPAM) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_AP_SPAM) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_CSA) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_QUIET) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_AUTH) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH_MANUAL) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH_TARGETED) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BAD_MSG_TARGETED) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BAD_MSG) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SLEEP) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SLEEP_TARGETED) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SAE_COMMIT) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_MIMIC) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_FUNNY_BEACON) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_RICK_ROLL) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BEACON_LIST) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_ALL) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_FOX_HUNT) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_RAYBAN) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG_MON) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_FLIPPER) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_SIMPLE) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_SIMPLE_TWO) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_SOUR_APPLE) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_APPLE_JUICE) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_SWIFTPAIR_SPAM) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_SPAM_ALL) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_SAMSUNG_SPAM) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_GOOGLE_SPAM) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_FLIPPER_SPAM) ||
- (wifi_scan_obj.currentScanMode == BT_SPOOF_AIRTAG) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_WAR_DRIVE) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_WAR_DRIVE_CONT) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_SKIMMERS) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_EAPOL) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_ACTIVE_EAPOL) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_ACTIVE_LIST_EAPOL) ||
- (wifi_scan_obj.currentScanMode == WIFI_PACKET_MONITOR) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PACKET_RATE) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_ANALYZER))
- {
- wifi_scan_obj.StartScan(WIFI_SCAN_OFF);
-
- // Restore display state without full reinit to avoid screen flash
- #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
- display_obj.tft.setRotation(SCREEN_ORIENTATION);
- display_obj.clearScreen();
- #else
- display_obj.init();
- #endif
-
- // Take us back to the menu
- changeMenu(current_menu, true);
- }
-
- x = -1;
- y = -1;
-
- return;
- }
- #endif
-
- #endif
-
-
- // Check if any key coordinate boxes contain the touch coordinates
- // This is for when on a menu
- // Make sure to add certain scanning functions here or else
- // menu items will be selected while scans and attacks are running
- #ifdef HAS_ILI9341
- if ((wifi_scan_obj.currentScanMode != WIFI_ATTACK_BEACON_SPAM) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_AP_SPAM) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_CSA) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_QUIET) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_AUTH) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH_MANUAL) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH_TARGETED) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_BAD_MSG_TARGETED) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_BAD_MSG) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_SLEEP) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_SLEEP_TARGETED) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_SAE_COMMIT) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_MIMIC) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_PACKET_RATE) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_RAW_CAPTURE) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_CHAN_ANALYZER) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_CHAN_ACT) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_SIG_STREN) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_AP) &&
- (wifi_scan_obj.currentScanMode != BT_SCAN_FLOCK) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_PROBE) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_DEAUTH) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_FUNNY_BEACON) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_EAPOL) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_RICK_ROLL))
- {
- // Need this to set all keys to false
- /*for (uint8_t b = 0; b < BUTTON_ARRAY_LEN; b++) {
- if (pressed && display_obj.key[b].contains(t_x, t_y)) {
- display_obj.key[b].press(true); // tell the button it is pressed
- } else {
- display_obj.key[b].press(false); // tell the button it is NOT pressed
- }
- }*/
-
- // Detect up, down, select
- uint8_t menu_button = display_obj.menuButton(&t_x, &t_y, pressed);
-
- if (menu_button > -1) {
- if (menu_button == UP_BUTTON) {
- if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
- (wifi_scan_obj.currentScanMode == WIFI_CONNECTED) ||
- (wifi_scan_obj.currentScanMode == OTA_UPDATE)) {
- if (current_menu->selected > 0) {
- current_menu->selected--;
- // Page up
- if (current_menu->selected < this->menu_start_index) {
- this->buildButtons(current_menu, current_menu->selected);
- this->displayCurrentMenu(current_menu->selected);
- }
- this->buttonSelected(current_menu->selected - this->menu_start_index, current_menu->selected);
- if (!current_menu->list->get(current_menu->selected + 1).selected || (current_menu->list->get(current_menu->selected + 1).icon == SETTINGS && current_menu->list->get(current_menu->selected + 1).color == TFTLIGHTGREY))
- this->buttonNotSelected(current_menu->selected + 1 - this->menu_start_index, current_menu->selected + 1);
- }
- // Loop to end
- else {
- current_menu->selected = current_menu->list->size() - 1;
- if (current_menu->selected >= BUTTON_SCREEN_LIMIT) {
- this->buildButtons(current_menu, current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
- this->displayCurrentMenu(current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
- }
- this->buttonSelected(current_menu->selected, current_menu->selected);
- if (!current_menu->list->get(0).selected || (current_menu->list->get(0).icon == SETTINGS && current_menu->list->get(0).color == TFTLIGHTGREY))
- this->buttonNotSelected(0, this->menu_start_index);
- }
- }
- else if ((wifi_scan_obj.currentScanMode == WIFI_PACKET_MONITOR) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_EAPOL) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PACKET_RATE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_RAW_CAPTURE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_DEAUTH) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN)) {
- #ifndef HAS_DUAL_BAND
- if (wifi_scan_obj.set_channel < 14)
- wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel + 1);
- else
- wifi_scan_obj.changeChannel(1);
- #else
- if (wifi_scan_obj.dual_band_channel_index < DUAL_BAND_CHANNELS - 1)
- wifi_scan_obj.dual_band_channel_index++;
- else
- wifi_scan_obj.dual_band_channel_index = 0;
-
- wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
- #endif
- }
- else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) {
- #ifndef HAS_DUAL_BAND
- if (wifi_scan_obj.activity_page < MAX_CHANNEL / CHAN_PER_PAGE) {
- wifi_scan_obj.activity_page++;
- }
- #else
- if (wifi_scan_obj.activity_page < DUAL_BAND_CHANNELS / CHAN_PER_PAGE) {
- wifi_scan_obj.activity_page++;
- }
- #endif
- wifi_scan_obj.drawChannelLine();
- }
- }
- if (menu_button == DOWN_BUTTON) {
- if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
- (wifi_scan_obj.currentScanMode == WIFI_CONNECTED) ||
- (wifi_scan_obj.currentScanMode == OTA_UPDATE)) {
- if (current_menu->selected < current_menu->list->size() - 1) {
- current_menu->selected++;
- // Page down
- if (current_menu->selected - this->menu_start_index >= BUTTON_SCREEN_LIMIT) {
- this->buildButtons(current_menu, current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
- this->displayCurrentMenu(current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
- }
- else
- this->buttonSelected(current_menu->selected - this->menu_start_index, current_menu->selected);
- if (!current_menu->list->get(current_menu->selected - 1).selected || (current_menu->list->get(current_menu->selected - 1).icon == SETTINGS && current_menu->list->get(current_menu->selected - 1).color == TFTLIGHTGREY))
- this->buttonNotSelected(current_menu->selected - 1 - this->menu_start_index, current_menu->selected - 1);
- }
- // Loop to beginning
- else {
- if (current_menu->selected >= BUTTON_SCREEN_LIMIT) {
- current_menu->selected = 0;
- this->buildButtons(current_menu);
- this->displayCurrentMenu();
- this->buttonSelected(current_menu->selected);
- }
- else {
- current_menu->selected = 0;
- this->buttonSelected(current_menu->selected);
- if (!current_menu->list->get(current_menu->list->size() - 1).selected || (current_menu->list->get(current_menu->list->size() - 1).icon == SETTINGS && current_menu->list->get(current_menu->list->size() - 1).color == TFTLIGHTGREY))
- this->buttonNotSelected(current_menu->list->size() - 1);
- }
- }
- }
- else if ((wifi_scan_obj.currentScanMode == WIFI_PACKET_MONITOR) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_EAPOL) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PACKET_RATE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_RAW_CAPTURE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_DEAUTH) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN)) {
- #ifndef HAS_DUAL_BAND
- if (wifi_scan_obj.set_channel > 1)
- wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel - 1);
- else
- wifi_scan_obj.changeChannel(14);
- #else
- if (wifi_scan_obj.dual_band_channel_index > 0)
- wifi_scan_obj.dual_band_channel_index--;
- else
- wifi_scan_obj.dual_band_channel_index = DUAL_BAND_CHANNELS - 1;
-
- wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
- #endif
- }
- else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) {
- #ifndef HAS_DUAL_BAND
- if (wifi_scan_obj.activity_page > 1) {
- wifi_scan_obj.activity_page--;
- }
- #else
- if (wifi_scan_obj.activity_page > 0) {
- wifi_scan_obj.activity_page--;
- }
- #endif
- wifi_scan_obj.drawChannelLine();
- }
- }
- if(menu_button == SELECT_BUTTON) {
- current_menu->list->get(current_menu->selected).callable();
- }
- else {
- if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
- (wifi_scan_obj.currentScanMode == WIFI_CONNECTED))
- this->displayMenuButtons();
- }
- }
- }
- x = -1;
- y = -1;
- #endif
-
- // Menu navigation and paging
- #ifdef HAS_BUTTONS
- // Don't do this for touch screens
- #if !(defined(MARAUDER_V6) || defined(MARAUDER_V6_1) || defined(MARAUDER_CYD_MICRO) || defined(MARAUDER_CYD_GUITION) || defined(MARAUDER_CYD_2USB) || defined(MARAUDER_CYD_3_5_INCH))
- #if !defined(MARAUDER_M5STICKC) || defined(MARAUDER_M5STICKCP2)
- #if (U_BTN >= 0 || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV))
- #if (U_BTN >= 0)
- if (u_btn.justPressed()) {
- #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
- if (this->isKeyPressed(';')) {
- #endif
- if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
- (wifi_scan_obj.currentScanMode == WIFI_CONNECTED) ||
- (wifi_scan_obj.currentScanMode == OTA_UPDATE)) {
- if (current_menu->selected > 0) {
- current_menu->selected--;
- // Page up
- if (current_menu->selected < this->menu_start_index) {
- this->buildButtons(current_menu, current_menu->selected);
- this->displayCurrentMenu(current_menu->selected);
- }
- this->buttonSelected(current_menu->selected - this->menu_start_index, current_menu->selected);
- if (!current_menu->list->get(current_menu->selected + 1).selected || (current_menu->list->get(current_menu->selected + 1).icon == SETTINGS && current_menu->list->get(current_menu->selected + 1).color == TFTLIGHTGREY))
- this->buttonNotSelected(current_menu->selected + 1 - this->menu_start_index, current_menu->selected + 1);
- }
- // Loop to end
- else {
- current_menu->selected = current_menu->list->size() - 1;
- if (current_menu->selected >= BUTTON_SCREEN_LIMIT) {
- this->buildButtons(current_menu, current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
- this->displayCurrentMenu(current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
- }
- this->buttonSelected(current_menu->selected, current_menu->selected);
- if (!current_menu->list->get(0).selected || (current_menu->list->get(0).icon == SETTINGS && current_menu->list->get(0).color == TFTLIGHTGREY))
- this->buttonNotSelected(0, this->menu_start_index);
- }
- }
- else if ((wifi_scan_obj.currentScanMode == WIFI_PACKET_MONITOR) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_EAPOL) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PACKET_RATE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_RAW_CAPTURE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_DEAUTH) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN)) {
- #ifndef HAS_DUAL_BAND
- if (wifi_scan_obj.set_channel < 14)
- wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel + 1);
- else
- wifi_scan_obj.changeChannel(1);
- #else
- if (wifi_scan_obj.dual_band_channel_index < DUAL_BAND_CHANNELS - 1)
- wifi_scan_obj.dual_band_channel_index++;
- else
- wifi_scan_obj.dual_band_channel_index = 0;
-
- wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
- #endif
- }
- else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) {
- #ifndef HAS_DUAL_BAND
- if (wifi_scan_obj.activity_page < MAX_CHANNEL / CHAN_PER_PAGE) {
- wifi_scan_obj.activity_page++;
- }
- #else
- if (wifi_scan_obj.activity_page < DUAL_BAND_CHANNELS / CHAN_PER_PAGE) {
- wifi_scan_obj.activity_page++;
- }
- #endif
- wifi_scan_obj.drawChannelLine();
- }
- }
- #endif
- #endif
-
- #if (D_BTN >= 0 || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV))
- #if (D_BTN >= 0)
- if (d_btn.justPressed()){
- #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
- if (this->isKeyPressed('.')){
- #endif
- if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
- (wifi_scan_obj.currentScanMode == WIFI_CONNECTED) ||
- (wifi_scan_obj.currentScanMode == OTA_UPDATE)) {
- if (current_menu->selected < current_menu->list->size() - 1) {
- current_menu->selected++;
- // Page down
- if (current_menu->selected - this->menu_start_index >= BUTTON_SCREEN_LIMIT) {
- this->buildButtons(current_menu, current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
- this->displayCurrentMenu(current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
- }
- else
- this->buttonSelected(current_menu->selected - this->menu_start_index, current_menu->selected);
- if (!current_menu->list->get(current_menu->selected - 1).selected || (current_menu->list->get(current_menu->selected - 1).icon == SETTINGS && current_menu->list->get(current_menu->selected - 1).color == TFTLIGHTGREY))
- this->buttonNotSelected(current_menu->selected - 1 - this->menu_start_index, current_menu->selected - 1);
- }
- // Loop to beginning
- else {
- if (current_menu->selected >= BUTTON_SCREEN_LIMIT) {
- current_menu->selected = 0;
- this->buildButtons(current_menu);
- this->displayCurrentMenu();
- this->buttonSelected(current_menu->selected);
- }
- else {
- current_menu->selected = 0;
- this->buttonSelected(current_menu->selected);
- if (!current_menu->list->get(current_menu->list->size() - 1).selected || (current_menu->list->get(current_menu->list->size() - 1).icon == SETTINGS && current_menu->list->get(current_menu->list->size() - 1).color == TFTLIGHTGREY))
- this->buttonNotSelected(current_menu->list->size() - 1);
- }
- }
- }
- else if ((wifi_scan_obj.currentScanMode == WIFI_PACKET_MONITOR) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_EAPOL) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PACKET_RATE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_RAW_CAPTURE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_DEAUTH) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN)) {
- #ifndef HAS_DUAL_BAND
- if (wifi_scan_obj.set_channel > 1)
- wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel - 1);
- else
- wifi_scan_obj.changeChannel(14);
- #else
- if (wifi_scan_obj.dual_band_channel_index > 0)
- wifi_scan_obj.dual_band_channel_index--;
- else
- wifi_scan_obj.dual_band_channel_index = DUAL_BAND_CHANNELS - 1;
-
- wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
- #endif
- }
- else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) {
- #ifndef HAS_DUAL_BAND
- if (wifi_scan_obj.activity_page > 1) {
- wifi_scan_obj.activity_page--;
- }
- #else
- if (wifi_scan_obj.activity_page > 0) {
- wifi_scan_obj.activity_page--;
- }
- #endif
- wifi_scan_obj.drawChannelLine();
- }
- }
- #endif
-
- #if (R_BTN >= 0 || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV))
- #if (R_BTN >= 0)
- if (r_btn.justPressed()) {
- #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
- if (this->isKeyPressed('/')) {
- #endif
- if (wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) {
- #ifndef HAS_DUAL_BAND
- if (wifi_scan_obj.set_channel < 14)
- wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel + 1);
- else
- wifi_scan_obj.changeChannel(1);
- #else
- if (wifi_scan_obj.dual_band_channel_index < DUAL_BAND_CHANNELS - 1)
- wifi_scan_obj.dual_band_channel_index++;
- else
- wifi_scan_obj.dual_band_channel_index = 0;
-
- wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
- #endif
- }
- }
- #endif
-
- #if (L_BTN >= 0 || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV))
- #if (L_BTN >= 0)
- if (l_btn.justPressed()) {
- #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
- if (this->isKeyPressed(',')) {
- #endif
- if (wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) {
- #ifndef HAS_DUAL_BAND
- if (wifi_scan_obj.set_channel > 1)
- wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel - 1);
- else
- wifi_scan_obj.changeChannel(14);
- #else
- if (wifi_scan_obj.dual_band_channel_index > 0)
- wifi_scan_obj.dual_band_channel_index--;
- else
- wifi_scan_obj.dual_band_channel_index = DUAL_BAND_CHANNELS - 1;
-
- wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
- #endif
- }
- }
- #endif
-
- #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
- if (this->isKeyPressed('`') || this->isKeyPressed(KEY_BACKSPACE)) {
- if (wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) {
- if (current_menu->parentMenu != NULL) {
- this->changeMenu(current_menu->parentMenu, true);
- }
- }
- }
- #endif
-
- if(c_btn_press){
- current_menu->list->get(current_menu->selected).callable();
- }
-
- #endif
- #endif
-}
-
-#if BATTERY_ANALOG_ON == 1
-byte battery_analog_array[10];
-byte battery_count = 0;
-byte battery_analog_last = 101;
-#define BATTERY_CHECK 50
-uint16_t battery_analog = 0;
-void MenuFunctions::battery(bool initial)
-{
- if (BATTERY_ANALOG_ON) {
- uint8_t n = 0;
- byte battery_analog_sample[10];
- byte deviation;
- if (battery_count == BATTERY_CHECK - 5) digitalWrite(BATTERY_PIN, HIGH);
- else if (battery_count == 5) digitalWrite(BATTERY_PIN, LOW);
- if (battery_count == 0) {
- battery_analog = 0;
- for (n = 9; n > 0; n--)battery_analog_array[n] = battery_analog_array[n - 1];
- for (n = 0; n < 10; n++) {
- battery_analog_sample[n] = map((analogRead(ANALOG_PIN) * 5), 2400, 4200, 0, 100);
- if (battery_analog_sample[n] > 100) battery_analog_sample[n] = 100;
- else if (battery_analog_sample[n] < 0) battery_analog_sample[n] = 0;
- battery_analog += battery_analog_sample[n];
- }
- battery_analog = battery_analog / 10;
- for (n = 0; n < 10; n++) {
- deviation = abs(battery_analog - battery_analog_sample[n]);
- if (deviation >= 10) battery_analog_sample[n] = battery_analog;
- }
- battery_analog = 0;
- for (n = 0; n < 10; n++) battery_analog += battery_analog_sample[n];
- battery_analog = battery_analog / 10;
- battery_analog_array[0] = battery_analog;
- if (battery_analog_array[9] > 0 ) {
- battery_analog = 0;
- for (n = 0; n < 10; n++) battery_analog += battery_analog_array[n];
- battery_analog = battery_analog / 10;
- }
- battery_count ++;
- }
- else if (battery_count < BATTERY_CHECK) battery_count++;
- else if (battery_count >= BATTERY_CHECK) battery_count = 0;
-
- if (battery_analog_last != battery_analog) {
- battery_analog_last = battery_analog;
- MenuFunctions::battery2();
- }
- }
-}
-void MenuFunctions::battery2(bool initial)
-{
- uint16_t the_color;
- if ( digitalRead(CHARGING_PIN) == 1) the_color = TFT_BLUE;
- else if (battery_analog < 20) the_color = TFT_RED;
- else if (battery_analog < 40) the_color = TFT_YELLOW;
- else the_color = TFT_GREEN;
-
- display_obj.tft.setTextColor(the_color, STATUSBAR_COLOR);
- display_obj.tft.fillRect(SB_TOUCH_X, 0, 50, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
- display_obj.tft.drawXBitmap(SB_TOUCH_X,
- 0,
- menu_icons[STATUS_BAT],
- 16,
- 16,
- STATUSBAR_COLOR,
- the_color);
- display_obj.tft.drawString((String) battery_analog + "%", SB_BAT_X, 0, 2);
-}
-#else
-void MenuFunctions::battery(bool initial)
-{
- #ifdef HAS_BATTERY
- uint16_t the_color;
- if (battery_obj.i2c_supported)
- {
- // Could use int compare maybe idk
- if (((String)battery_obj.battery_level != "25") && ((String)battery_obj.battery_level != "0"))
- the_color = TFT_GREEN;
- else
- the_color = TFT_RED;
-
- if ((battery_obj.battery_level != battery_obj.old_level) || (initial)) {
- battery_obj.old_level = battery_obj.battery_level;
- display_obj.tft.fillRect(204, 0, SCREEN_WIDTH, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
- }
-
- display_obj.tft.setCursor(0, 1);
- /*if (!this->disable_touch) {
- display_obj.tft.drawXBitmap(SB_TOUCH_X,
- 0,
- menu_icons[STATUS_BAT],
- 16,
- 16,
- STATUSBAR_COLOR,
- the_color);
- }*/
- #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
- display_obj.tft.drawString((String)battery_obj.battery_level + "%", SB_BAT_X, 0, 1);
- #else
- display_obj.tft.drawString((String)battery_obj.battery_level + "%", SB_BAT_X, 0, 2);
- #endif
- }
- #endif
-}
-void MenuFunctions::battery2(bool initial)
-{
- MenuFunctions::battery(initial);
-}
-#endif
-
-void MenuFunctions::updateStatusBar()
-{
- display_obj.tft.setTextSize(1);
-
- bool status_changed = false;
-
- #if defined(MARAUDER_MINI) || defined(MARAUDER_M5STICKC) || defined(MARAUDER_REV_FEATHER) || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) || defined(MARAUDER_MINI_V3)
- display_obj.tft.setFreeFont(NULL);
- #endif
-
- uint16_t the_color;
-
- #ifdef HAS_GPS
- if (this->old_gps_sat_count != gps_obj.getNumSats()) {
- this->old_gps_sat_count = gps_obj.getNumSats();
- display_obj.tft.fillRect(0, 0, SCREEN_WIDTH, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
- status_changed = true;
- }
- #endif
-
- // GPS Stuff
- #ifdef HAS_GPS
- if (gps_obj.getGpsModuleStatus()) {
- if (gps_obj.getFixStatus())
- the_color = TFT_GREEN;
- else
- the_color = TFT_RED;
-
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(4,
- 0,
- menu_icons[STATUS_GPS],
- 16,
- 16,
- STATUSBAR_COLOR,
- the_color);
- display_obj.tft.setTextColor(TFT_WHITE, STATUSBAR_COLOR, true);
-
- display_obj.tft.drawString(gps_obj.getNumSatsString(), 22, 0, 2);
- #elif defined(HAS_SCREEN)
- display_obj.tft.setTextColor(the_color, STATUSBAR_COLOR, true);
- display_obj.tft.drawString("GPS", 0, 0, 1);
- #endif
- }
- #endif
-
- display_obj.tft.setTextColor(TFT_WHITE, STATUSBAR_COLOR, true);
-
- // WiFi Channel Stuff
- uint8_t primaryChannel;
- wifi_second_chan_t secondChannel;
- esp_err_t err = esp_wifi_get_channel(&primaryChannel, &secondChannel);
-
- uint8_t current_channel = wifi_scan_obj.set_channel;
-
- if (err == ESP_OK)
- current_channel = primaryChannel;
-
- if ((current_channel != wifi_scan_obj.old_channel) || (status_changed)) {
- wifi_scan_obj.old_channel = current_channel;
- #if defined(MARAUDER_MINI) || defined(MARAUDER_M5STICKC) || defined(MARAUDER_REV_FEATHER) || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) || defined(MARAUDER_MINI_V3)
- display_obj.tft.fillRect(TFT_WIDTH/4, 0, CHAR_WIDTH * 6, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
- #elif defined(HAS_DUAL_BAND)
- display_obj.tft.fillRect(50, 0, (CHAR_WIDTH / 2) * 8, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
- #else
- display_obj.tft.fillRect(50, 0, (CHAR_WIDTH / 2) * 7, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
- #endif
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawString("CH: " + (String)wifi_scan_obj.old_channel, 50, 0, 2);
- #endif
-
- #ifdef HAS_MINI_SCREEN
- display_obj.tft.drawString("CH:" + (String)wifi_scan_obj.old_channel, TFT_WIDTH/4, 0, 1);
- #endif
- }
-
- // RAM Stuff
- wifi_scan_obj.free_ram = String(esp_get_free_heap_size());
- if ((wifi_scan_obj.free_ram != wifi_scan_obj.old_free_ram) || (status_changed)) {
- wifi_scan_obj.old_free_ram = wifi_scan_obj.free_ram;
- //display_obj.tft.fillRect(SB_MEM_X, 0, 60, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
- #ifdef HAS_FULL_SCREEN
- #ifndef HAS_PSRAM
- display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", SB_MEM_X, 0, 2);
- #else
- display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", SB_MEM_X, 0, 1);
- display_obj.tft.drawString("P:" + String(getPSRAMUsagePercent()) + "%", SB_MEM_X, 8, 1);
- #endif
- #endif
-
- #ifdef HAS_MINI_SCREEN
- display_obj.tft.drawString(String(getDRAMUsagePercent()) + "%", TFT_WIDTH/1.75, 0, 1);
- #endif
- }
-
- // Draw battery info
- MenuFunctions::battery(false);
- display_obj.tft.fillRect(186, 0, 16, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
-
- // Disable touch stuff
- #ifdef HAS_ILI9341
- #ifdef HAS_BUTTONS
- if (this->disable_touch) {
- display_obj.tft.setCursor(0, 1);
- display_obj.tft.drawXBitmap(SB_TOUCH_X,
- 0,
- menu_icons[DISABLE_TOUCH],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_RED);
- }
- else {
- display_obj.tft.setCursor(0, 1);
- display_obj.tft.drawXBitmap(SB_TOUCH_X,
- 0,
- menu_icons[DISABLE_TOUCH],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_DARKGREY);
- }
- #endif
- #endif
-
- // Draw SD info
- #ifdef HAS_SD
- if (sd_obj.supported)
- the_color = TFT_GREEN;
- else
- the_color = TFT_RED;
-
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(SB_SD_X,
- 0,
- menu_icons[STATUS_SD],
- 16,
- 16,
- STATUSBAR_COLOR,
- the_color);
- #endif
- #endif
-
- #ifdef HAS_MINI_SCREEN
- display_obj.tft.setTextColor(the_color, STATUSBAR_COLOR, true);
- display_obj.tft.drawString("SD", TFT_WIDTH - 12, 0, 1);
- #endif
-
- // WiFi connection status stuff
- if (wifi_scan_obj.wifi_connected) {
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(SB_WIFI_X,
- 0,
- menu_icons[JOINED],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_GREEN);
- #endif
- } else {
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(SB_WIFI_X,
- 0,
- menu_icons[JOINED],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_DARKGREY);
- #endif
- }
-
- // Force PMKID stuff
- if ((wifi_scan_obj.force_pmkid) || (wifi_scan_obj.ep_deauth)) {
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(SB_FORCE_X,
- 0,
- menu_icons[FORCE],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_GREEN);
- #endif
- } else {
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(SB_FORCE_X,
- 0,
- menu_icons[FORCE],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_DARKGREY);
- #endif
- }
-}
-
-void MenuFunctions::drawStatusBar()
-{
- display_obj.tft.setTextSize(1);
- #ifdef HAS_MINI_SCREEN
- display_obj.tft.setFreeFont(NULL);
- #endif
- display_obj.tft.fillRect(0, 0, SCREEN_WIDTH, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
- display_obj.tft.setTextColor(TFT_WHITE, STATUSBAR_COLOR);
-
- uint16_t the_color;
-
- // GPS Stuff
- #ifdef HAS_GPS
- if (gps_obj.getGpsModuleStatus()) {
- if (gps_obj.getFixStatus())
- the_color = TFT_GREEN;
- else
- the_color = TFT_RED;
-
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(4,
- 0,
- menu_icons[STATUS_GPS],
- 16,
- 16,
- STATUSBAR_COLOR,
- the_color);
- display_obj.tft.setTextColor(TFT_WHITE, STATUSBAR_COLOR);
-
- display_obj.tft.drawString(gps_obj.getNumSatsString(), 22, 0, 2);
- #endif
- }
- #endif
-
- display_obj.tft.setTextColor(TFT_WHITE, STATUSBAR_COLOR);
-
-
- // WiFi Channel Stuff
- uint8_t primaryChannel;
- wifi_second_chan_t secondChannel;
- esp_err_t err = esp_wifi_get_channel(&primaryChannel, &secondChannel);
-
- if (err == ESP_OK)
- wifi_scan_obj.old_channel = primaryChannel;
- else
- wifi_scan_obj.old_channel = wifi_scan_obj.set_channel;
-
- #ifdef HAS_MINI_SCREEN
- display_obj.tft.fillRect(43, 0, TFT_WIDTH * 0.21, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
- #else
- display_obj.tft.fillRect(50, 0, TFT_WIDTH * 0.21, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
- #endif
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawString("CH: " + (String)wifi_scan_obj.old_channel, 50, 0, 2);
- #endif
-
- #ifdef HAS_MINI_SCREEN
- display_obj.tft.drawString("CH:" + (String)wifi_scan_obj.old_channel, TFT_WIDTH/4, 0, 1);
- #endif
-
- // RAM Stuff
- wifi_scan_obj.free_ram = String(esp_get_free_heap_size());
- wifi_scan_obj.old_free_ram = wifi_scan_obj.free_ram;
- display_obj.tft.fillRect(100, 0, 60, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
- #ifdef HAS_FULL_SCREEN
- #ifndef HAS_PSRAM
- display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", SB_MEM_X, 0, 2);
- #else
- display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", SB_MEM_X, 0, 1);
- display_obj.tft.drawString("P:" + String(getPSRAMUsagePercent()) + "%", SB_MEM_X, 8, 1);
- #endif
- #endif
-
- #ifdef HAS_MINI_SCREEN
- display_obj.tft.drawString(String(getDRAMUsagePercent()) + "%", TFT_WIDTH/1.75, 0, 1);
- #endif
-
-
- MenuFunctions::battery(true);
- display_obj.tft.fillRect(186, 0, 16, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
-
-
- // Disable touch stuff
- #ifdef HAS_ILI9341
- #ifdef HAS_BUTTONS
- if (this->disable_touch) {
- display_obj.tft.setCursor(0, 1);
- display_obj.tft.drawXBitmap(SB_TOUCH_X,
- 0,
- menu_icons[DISABLE_TOUCH],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_RED);
- }
- else {
- display_obj.tft.setCursor(0, 1);
- display_obj.tft.drawXBitmap(SB_TOUCH_X,
- 0,
- menu_icons[DISABLE_TOUCH],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_DARKGREY);
- }
- #endif
- #endif
-
- // Draw SD info
- #ifdef HAS_SD
- if (sd_obj.supported)
- the_color = TFT_GREEN;
- else
- the_color = TFT_RED;
-
-
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(SB_SD_X,
- 0,
- menu_icons[STATUS_SD],
- 16,
- 16,
- STATUSBAR_COLOR,
- the_color);
- #endif
- #endif
-
- #ifdef HAS_MINI_SCREEN
- display_obj.tft.setTextColor(the_color, STATUSBAR_COLOR);
- display_obj.tft.drawString("SD", TFT_WIDTH - 12, 0, 1);
- #endif
-
- // WiFi connection status stuff
- if (wifi_scan_obj.wifi_connected) {
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(SB_WIFI_X,
- 0,
- menu_icons[JOINED],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_GREEN);
- #endif
- } else {
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(SB_WIFI_X,
- 0,
- menu_icons[JOINED],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_DARKGREY);
- #endif
- }
-
- // Force PMKID stuff
- if ((wifi_scan_obj.force_pmkid) || (wifi_scan_obj.ep_deauth)) {
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(SB_FORCE_X,
- 0,
- menu_icons[FORCE],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_GREEN);
- #endif
- } else {
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(SB_FORCE_X,
- 0,
- menu_icons[FORCE],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_DARKGREY);
- #endif
- }
-}
-
-void MenuFunctions::orientDisplay() {
- display_obj.init();
-
- display_obj.tft.setRotation(SCREEN_ORIENTATION); // Portrait
-
- display_obj.tft.setCursor(0, 0);
-
- #ifdef HAS_ILI9341
- #ifndef HAS_CYD_TOUCH
- display_obj.setCalData();
- #else
- display_obj.touchscreen.setRotation(0);
- #endif
- #endif
-
- changeMenu(current_menu, true);
-}
-
-const char* MenuFunctions::callSetting(const char* key) {
- specSettingMenu.name = key;
-
- const char* setting_type = settings_obj.getSettingType(key);
-
- if (setting_type && strcmp(setting_type, "bool") == 0) {
- return "bool";
- }
-
- return "";
-}
-
-/*void MenuFunctions::displaySetting(String key, Menu* menu, int index) {
- specSettingMenu.name = key;
-
- bool setting_value = settings_obj.loadSetting(key);
-
- // Make a local copy of menu node
- MenuNode node = menu->list->get(index);
-
- display_obj.tft.setTextWrap(false);
- display_obj.tft.setFreeFont(NULL);
- display_obj.tft.setCursor(0, 100);
- display_obj.tft.setTextSize(1);
-
- // Set local copy value
- if (!setting_value) {
- display_obj.tft.setTextColor(TFT_RED);
- display_obj.tft.println(F(text_table1[4]));
- node.selected = false;
- }
- else {
- display_obj.tft.setTextColor(TFT_GREEN);
- display_obj.tft.println(F(text_table1[5]));
- node.selected = true;
- }
-
- // Put local copy back into menu
- menu->list->set(index, node);
-
-}*/
-
-void MenuFunctions::displaySetting(const char* key, Menu* menu, int index) {
- specSettingMenu.name = String(key);
-
- bool setting_value = settings_obj.loadSetting(key);
-
- // Make a local copy of menu node
- MenuNode node = menu->list->get(index);
-
- display_obj.tft.setTextWrap(false);
- display_obj.tft.setFreeFont(NULL);
- display_obj.tft.setCursor(0, 100);
- display_obj.tft.setTextSize(1);
-
- // Set local copy value
- if (!setting_value) {
- display_obj.tft.setTextColor(TFT_RED);
- display_obj.tft.println(F(text_table1[4]));
- node.selected = false;
- } else {
- display_obj.tft.setTextColor(TFT_GREEN);
- display_obj.tft.println(F(text_table1[5]));
- node.selected = true;
- }
-
- // Put local copy back into menu
- menu->list->set(index, node);
-}
-
-#if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
-void MenuFunctions::updateKeyboard()
-{
- M5CardputerKeyboard.updateKeyList();
- M5CardputerKeyboard.updateKeysState();
-}
-
-bool MenuFunctions::isKeyPressed(char c)
-{
- bool pressed = M5CardputerKeyboard.isKeyPressed(c);
-
- if (pressed)
- delay(200);
-
- return pressed;
-}
-#endif
-
-#ifdef HAS_DIRECT_UPLOAD
- void MenuFunctions::buildUploadFileMenu() {
- if (sd_obj.supported) {
- this->setupSDFileList();
-
- uploadLogsMenu.list->clear();
- delete uploadLogsMenu.list;
- uploadLogsMenu.list = new LinkedList();
- uploadLogsMenu.name = "Logs";
-
- uploadLogsMenu.parentMenu = &wifiGeneralMenu;
-
- this->addNodes(&uploadLogsMenu, "Back", TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(uploadLogsMenu.parentMenu, true);
- });
-
- this->addNodes(&uploadLogsMenu, "Delete Wardrive Logs", TFTORANGE, 0, [this]() {
- this->changeMenu(&deleteAllMenu, true);
- });
-
- this->addNodes(&uploadLogsMenu, "Upload All", TFTGREEN, 0, [this]() {
- this->changeMenu(&uploadAllMenu, true);
-
- });
-
- for (int i = 0; i < sd_obj.sd_files->size(); i++) {
- File current_file = sd_obj.getFile("/" + sd_obj.sd_files->get(i));
- if (sd_obj.sd_files->get(i).startsWith("wardrive_") || sd_obj.sd_files->get(i).startsWith("wigle-")) {
- if (!sd_obj.sd_files->get(i).endsWith(".wdg") && !sd_obj.sd_files->get(i).endsWith(".wigle") && !sd_obj.sd_files->get(i).endsWith(".gpx")) {
- this->addNodes(&uploadLogsMenu, sd_obj.sd_files->get(i).c_str(), TFTCYAN, 0, [this, i]() {
- sd_obj.selected_file_name = sd_obj.sd_files->get(i);
- Serial.println(sd_obj.sd_files->get(i) + " selected");
- this->changeMenu(&actionMenu, true);
- });
- }
- }
- }
-
- Serial.println("Built SD file menu with " + (String)sd_obj.sd_files->size() + " files");
- } else {
- Serial.println("SD Card not detected. Skipping menu creation...");
- }
- }
+
+#ifdef HAS_MINI_SCREEN
+void MenuFunctions::drawMiniMenuButton(int b, int x, bool selected) {
+ if (!current_menu || !current_menu->list || x < 0 || x >= current_menu->list->size())
+ return;
+
+ MenuNode mini_node = current_menu->list->get(x);
+ bool is_setting_node = (mini_node.icon == SETTINGS && mini_node.color == TFTLIGHTGREY);
+ uint16_t color = is_setting_node ? (mini_node.selected ? TFT_GREEN : TFT_RED) : this->getColor(mini_node.color);
+ int16_t button_x = KEY_X - (KEY_W / 2);
+ int16_t button_y = (KEY_Y + (b * (KEY_H + KEY_SPACING_Y))) - (KEY_H / 2);
+
+ uint16_t background = selected ? (is_setting_node ? TFT_LIGHTGREY : color) : TFT_BLACK;
+ uint16_t text_color = (selected && !is_setting_node) ? TFT_BLACK : color;
+
+ display_obj.tft.setFreeFont(NULL);
+ display_obj.tft.setTextSize(1);
+ display_obj.tft.setTextWrap(false);
+ display_obj.tft.fillRect(button_x, button_y - 4, KEY_W, KEY_H, background);
+ display_obj.tft.setTextColor(text_color, background);
+ display_obj.tft.setCursor(button_x + BUTTON_PADDING, button_y + (KEY_H / 2) - 8);
+ display_obj.tft.print(current_menu->list->get(x).name);
+}
+#endif
+
+void MenuFunctions::buttonNotSelected(int b, int x) {
+ if (x == -1)
+ x = b;
+
+ // Ensure b is within valid button index range
+ b = (x - menu_start_index) % BUTTON_SCREEN_LIMIT;
+
+ #ifdef HAS_MINI_SCREEN
+ this->drawMiniMenuButton(b, x, false);
+ #endif
+
+ uint16_t color = (current_menu->list->get(x).icon == SETTINGS && current_menu->list->get(x).color == TFTLIGHTGREY) ? (current_menu->list->get(x).selected ? TFT_GREEN : TFT_RED) : this->getColor(current_menu->list->get(x).color);
+ uint16_t icon_color = (current_menu->list->get(x).icon == SETTINGS && current_menu->list->get(x).color == TFTLIGHTGREY) ? TFT_LIGHTGREY : color;
+
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.setFreeFont(MENU_FONT);
+ display_obj.key[b].initButton(&display_obj.tft, KEY_X, KEY_Y + b * (KEY_H + KEY_SPACING_Y), KEY_W, KEY_H, TFT_BLACK, TFT_BLACK, color, (char*)"", KEY_TEXTSIZE);
+ display_obj.key[b].drawButton(false, current_menu->list->get(x).name);
+ if ((current_menu->list->get(x).name != text09) && (current_menu->list->get(x).icon != 255))
+ display_obj.tft.drawXBitmap(0,
+ KEY_Y + (b * (KEY_H + KEY_SPACING_Y)) - (ICON_H / 2),
+ menu_icons[current_menu->list->get(x).icon],
+ ICON_W,
+ ICON_H,
+ TFT_BLACK,
+ icon_color);
+ display_obj.tft.setFreeFont(NULL);
+ #endif
+}
+
+void MenuFunctions::buttonSelected(int b, int x) {
+ if (x == -1)
+ x = b;
+
+ // Ensure b is within valid button index range
+ b = (x - menu_start_index) % BUTTON_SCREEN_LIMIT;
+
+ uint16_t color = this->getColor(current_menu->list->get(x).color);
+
+ #ifdef HAS_MINI_SCREEN
+ this->drawMiniMenuButton(b, x, true);
+ #endif
+
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.setFreeFont(MENU_FONT);
+ if (current_menu->list->get(x).icon == SETTINGS && current_menu->list->get(x).color == TFTLIGHTGREY) {
+ uint16_t setting_color = current_menu->list->get(x).selected ? TFT_GREEN : TFT_RED;
+ display_obj.key[b].initButton(&display_obj.tft, KEY_X, KEY_Y + b * (KEY_H + KEY_SPACING_Y), KEY_W, KEY_H, TFT_BLACK, TFT_LIGHTGREY, setting_color, (char*)"", KEY_TEXTSIZE);
+ display_obj.key[b].drawButton(false, current_menu->list->get(x).name);
+ display_obj.tft.drawXBitmap(0,
+ KEY_Y + (b * (KEY_H + KEY_SPACING_Y)) - (ICON_H / 2),
+ menu_icons[current_menu->list->get(x).icon],
+ ICON_W,
+ ICON_H,
+ TFT_BLACK,
+ TFT_LIGHTGREY);
+ } else {
+ display_obj.key[b].drawButton(true, current_menu->list->get(x).name);
+ if ((current_menu->list->get(x).name != text09) && (current_menu->list->get(x).icon != 255))
+ display_obj.tft.drawXBitmap(0,
+ KEY_Y + (b * (KEY_H + KEY_SPACING_Y)) - (ICON_H / 2),
+ menu_icons[current_menu->list->get(x).icon],
+ ICON_W,
+ ICON_H,
+ TFT_BLACK,
+ color);
+ }
+ display_obj.tft.setFreeFont(NULL);
+ #endif
+}
+
+void MenuFunctions::displayMenuButtons() {
+ #ifdef HAS_ILI9341
+ // Draw lines to show each menu button
+ for (int i = 0; i < 3; i++) {
+
+ // Draw horizontal line on left
+ display_obj.tft.drawLine(0,
+ TFT_HEIGHT / 3 * (i),
+ (TFT_WIDTH / 12) / 2,
+ TFT_HEIGHT / 3 * (i),
+ TFT_FARTGRAY);
+
+ // Draw horizontal line on right
+ display_obj.tft.drawLine(TFT_WIDTH - 1 - ((TFT_WIDTH / 12) / 2),
+ TFT_HEIGHT / 3 * (i),
+ TFT_WIDTH,
+ TFT_HEIGHT / 3 * (i),
+ TFT_FARTGRAY);
+
+ // Draw vertical line on left
+ display_obj.tft.drawLine(0,
+ (TFT_HEIGHT / 3 * (i)) - ((TFT_WIDTH / 12) / 2),
+ 0,
+ (TFT_HEIGHT / 3 * (i)) + ((TFT_WIDTH / 12) / 2),
+ TFT_FARTGRAY);
+
+ // Draw vertical line on right
+ display_obj.tft.drawLine(TFT_WIDTH - 1,
+ (TFT_HEIGHT / 3 * (i)) - ((TFT_WIDTH / 12) / 2),
+ TFT_WIDTH - 1,
+ (TFT_HEIGHT / 3 * (i)) + ((TFT_WIDTH / 12) / 2),
+ TFT_FARTGRAY);
+ }
+ #endif
+}
+
+// Function to check menu input
+void MenuFunctions::main(uint32_t currentTime)
+{
+ #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+ this->updateKeyboard();
+ #endif
+
+ // Some function exited and we need to go back to normal
+ if (display_obj.exit_draw) {
+ if (wifi_scan_obj.currentScanMode != WIFI_CONNECTED)
+ wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF;
+ display_obj.exit_draw = false;
+ this->orientDisplay();
+ }
+ if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
+ (wifi_scan_obj.currentScanMode == WIFI_CONNECTED) ||
+ (wifi_scan_obj.currentScanMode == OTA_UPDATE) ||
+ (wifi_scan_obj.currentScanMode == ESP_UPDATE) ||
+ (wifi_scan_obj.currentScanMode == SHOW_INFO) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_GPS_DATA) ||
+ (wifi_scan_obj.currentScanMode == GPS_POI) ||
+ (wifi_scan_obj.currentScanMode == GPS_TRACKER) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_GPS_NMEA)) {
+ if (wifi_scan_obj.orient_display) {
+ this->orientDisplay();
+ wifi_scan_obj.orient_display = false;
+ }
+ }
+
+ if (currentTime != 0) {
+ if (currentTime - initTime >= BANNER_TIME) {
+ this->initTime = millis();
+ if ((wifi_scan_obj.currentScanMode != LV_JOIN_WIFI) &&
+ (wifi_scan_obj.currentScanMode != LV_ADD_SSID))
+ this->updateStatusBar();
+
+ // Do channel analyzer stuff
+ if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_ANALYZER)){
+ #ifdef HAS_SCREEN
+ this->setGraphScale(this->graphScaleCheck(wifi_scan_obj._analyzer_values));
+
+ this->drawGraph(wifi_scan_obj._analyzer_values);
+ #endif
+ }
+
+ if (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) {
+ #ifdef HAS_SCREEN
+ this->setGraphScale(this->graphScaleCheckSmall(wifi_scan_obj.channel_activity));
+
+ this->drawGraphSmall(wifi_scan_obj.channel_activity);
+
+ #endif
+ }
+ }
+ }
+
+
+ boolean pressed = false;
+ // This is code from bodmer's keypad example
+ uint16_t t_x = 0, t_y = 0; // To store the touch coordinates
+
+ // Get the display buffer out of the way
+ if ((wifi_scan_obj.currentScanMode != WIFI_SCAN_OFF ) &&
+ (wifi_scan_obj.currentScanMode != WIFI_CONNECTED) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_BEACON_SPAM) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_AP_SPAM) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_CSA) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_QUIET) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_AUTH) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH_MANUAL) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH_TARGETED) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_BAD_MSG_TARGETED) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_BAD_MSG) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_SLEEP) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_SLEEP_TARGETED) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_MIMIC) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_FUNNY_BEACON) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_RICK_ROLL))
+ display_obj.displayBuffer();
+
+
+ int pre_getTouch = millis();
+
+ #ifdef HAS_ILI9341
+ if (!this->disable_touch)
+ pressed = display_obj.updateTouch(&t_x, &t_y);
+ #endif
+
+
+ // Brightness gesture: hold top or bottom zone 1.5s to enter brightness mode
+ #ifdef HAS_ILI9341
+ if (pressed && (wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF ||
+ wifi_scan_obj.currentScanMode == WIFI_CONNECTED)) {
+ uint16_t zoneUp = TFT_HEIGHT * 25 / 100;
+ uint16_t zoneDown = TFT_HEIGHT * 75 / 100;
+ if (t_y < zoneUp || t_y >= zoneDown) {
+ uint32_t hold_start = millis();
+ uint16_t hx, hy;
+ bool held = false;
+ while (display_obj.updateTouch(&hx, &hy)) {
+ if (millis() - hold_start >= 1500) {
+ held = true;
+ break;
+ }
+ delay(10);
+ }
+ if (held) {
+ // Wait for release before entering brightness mode
+ while (display_obj.updateTouch(&hx, &hy)) delay(10);
+ this->brightnessMode();
+ return;
+ }
+ }
+ }
+ #endif
+
+ // POI button interception during wardrive — full width bottom bar
+ #ifdef HAS_ILI9341
+ if (pressed &&
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_WAR_DRIVE ||
+ wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION_WAR_DRIVE)) {
+ if (t_y >= (SCREEN_HEIGHT - 50)) {
+ wifi_scan_obj.tagPOI(nullptr);
+ // Brief green flash
+ display_obj.tft.fillRect(0, SCREEN_HEIGHT - 50, SCREEN_WIDTH, 50, TFT_GREEN);
+ display_obj.tft.setTextSize(2);
+ #ifdef HAS_GPS
+ if (gps_obj.getFixStatus())
+ display_obj.tft.setTextColor(TFT_BLACK, TFT_GREEN);
+ else
+ #endif
+ display_obj.tft.setTextColor(TFT_BLACK, TFT_RED);
+ String poiFlash = "POI (" + String(wifi_scan_obj.poiCount) + ")";
+ int16_t flashWidth = poiFlash.length() * 12;
+ display_obj.tft.setCursor((SCREEN_WIDTH - flashWidth) / 2, SCREEN_HEIGHT - 33);
+ display_obj.tft.print(poiFlash);
+ delay(200);
+ x = -1;
+ y = -1;
+ return;
+ }
+ }
+ #endif
+
+ // This is if there are scans/attacks going on
+ #ifdef HAS_ILI9341
+ if ((wifi_scan_obj.currentScanMode != WIFI_SCAN_OFF) &&
+ (pressed) &&
+ (wifi_scan_obj.currentScanMode != WIFI_CONNECTED) &&
+ (wifi_scan_obj.currentScanMode != OTA_UPDATE) &&
+ (wifi_scan_obj.currentScanMode != ESP_UPDATE) &&
+ (wifi_scan_obj.currentScanMode != SHOW_INFO) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_GPS_DATA) &&
+ (wifi_scan_obj.currentScanMode != GPS_POI) &&
+ (wifi_scan_obj.currentScanMode != GPS_TRACKER) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_GPS_NMEA))
+ {
+ // Stop the current scan
+ if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_SAE_COMMIT) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_DETECT_FOLLOW) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION_WAR_DRIVE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_WAR_DRIVE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_DISPLAY_AP_INFO) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_EVIL_PORTAL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP_STA) ||
+ (wifi_scan_obj.currentScanMode == WIFI_PING_SCAN) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ARP_SCAN) ||
+ (wifi_scan_obj.currentScanMode == WIFI_PORT_SCAN_ALL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_SSH) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_TELNET) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_DNS) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_SMTP) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_HTTP) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_HTTPS) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_RDP) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PWN) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PINESCAN) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_MULTISSID) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_ESPRESSIF) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_ALL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BEACON_SPAM) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_AP_SPAM) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_CSA) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_QUIET) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_AUTH) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH_MANUAL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH_TARGETED) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BAD_MSG_TARGETED) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BAD_MSG) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SLEEP) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SLEEP_TARGETED) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SAE_COMMIT) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_MIMIC) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_FUNNY_BEACON) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_RICK_ROLL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BEACON_LIST) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_ALL) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_FOX_HUNT) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_FINDMY_LIVE) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_RAYBAN) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG_MON) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_FLIPPER) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_SIMPLE) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_SIMPLE_TWO) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_SOUR_APPLE) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_APPLE_JUICE) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_SWIFTPAIR_SPAM) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_SPAM_ALL) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_SAMSUNG_SPAM) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_GOOGLE_SPAM) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_FLIPPER_SPAM) ||
+ (wifi_scan_obj.currentScanMode == BT_SPOOF_AIRTAG) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_WAR_DRIVE) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_WAR_DRIVE_CONT) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_SKIMMERS) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_ANALYZER))
+ {
+ wifi_scan_obj.StartScan(WIFI_SCAN_OFF);
+
+ // If we don't do this, the text and button coordinates will be off
+ display_obj.init();
+
+ // Take us back to the menu
+ changeMenu(current_menu, true);
+ }
+
+ x = -1;
+ y = -1;
+
+ return;
+ }
+ #endif
+
+ #ifdef HAS_BUTTONS
+
+ #if (C_BTN >= 0) && !defined(MARAUDER_CARDPUTER) && !defined(MARAUDER_CARDPUTER_ADV)
+ bool c_btn_press = c_btn.justPressed();
+ #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+ bool c_btn_press = this->isKeyPressed('(');
+ #endif
+
+ #ifndef HAS_ILI9341
+
+ if ((c_btn_press) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_OFF) &&
+ (wifi_scan_obj.currentScanMode != WIFI_CONNECTED) &&
+ (wifi_scan_obj.currentScanMode != OTA_UPDATE) &&
+ (wifi_scan_obj.currentScanMode != ESP_UPDATE) &&
+ (wifi_scan_obj.currentScanMode != SHOW_INFO) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_GPS_DATA) &&
+ (wifi_scan_obj.currentScanMode != GPS_POI) &&
+ (wifi_scan_obj.currentScanMode != GPS_TRACKER) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_GPS_NMEA))
+ {
+ // Stop the current scan
+ if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_SAE_COMMIT) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_DETECT_FOLLOW) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION_WAR_DRIVE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_RAW_CAPTURE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_WAR_DRIVE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_DISPLAY_AP_INFO) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_EVIL_PORTAL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_FINDMY_LIVE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP_STA) ||
+ (wifi_scan_obj.currentScanMode == WIFI_PING_SCAN) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ARP_SCAN) ||
+ (wifi_scan_obj.currentScanMode == WIFI_PORT_SCAN_ALL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_SSH) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_TELNET) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_DNS) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_SMTP) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_HTTP) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_HTTPS) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_RDP) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PWN) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PINESCAN) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_MULTISSID) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_ESPRESSIF) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_ALL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_DEAUTH) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BEACON_SPAM) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_AP_SPAM) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_CSA) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_QUIET) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_AUTH) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH_MANUAL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH_TARGETED) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BAD_MSG_TARGETED) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BAD_MSG) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SLEEP) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SLEEP_TARGETED) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SAE_COMMIT) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_MIMIC) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_FUNNY_BEACON) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_RICK_ROLL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BEACON_LIST) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_ALL) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_FOX_HUNT) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_RAYBAN) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG_MON) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_FLIPPER) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_SIMPLE) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_SIMPLE_TWO) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_SOUR_APPLE) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_APPLE_JUICE) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_SWIFTPAIR_SPAM) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_SPAM_ALL) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_SAMSUNG_SPAM) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_GOOGLE_SPAM) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_FLIPPER_SPAM) ||
+ (wifi_scan_obj.currentScanMode == BT_SPOOF_AIRTAG) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_WAR_DRIVE) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_WAR_DRIVE_CONT) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_SKIMMERS) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_EAPOL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_ACTIVE_EAPOL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_ACTIVE_LIST_EAPOL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_PACKET_MONITOR) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PACKET_RATE) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_ANALYZER))
+ {
+ wifi_scan_obj.StartScan(WIFI_SCAN_OFF);
+
+ // Restore display state without full reinit to avoid screen flash
+ #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+ display_obj.tft.setRotation(SCREEN_ORIENTATION);
+ display_obj.clearScreen();
+ #else
+ display_obj.init();
+ #endif
+
+ // Take us back to the menu
+ changeMenu(current_menu, true);
+ }
+
+ x = -1;
+ y = -1;
+
+ return;
+ }
+ #endif
+
+ #endif
+
+
+ // Check if any key coordinate boxes contain the touch coordinates
+ // This is for when on a menu
+ // Make sure to add certain scanning functions here or else
+ // menu items will be selected while scans and attacks are running
+ #ifdef HAS_ILI9341
+ if ((wifi_scan_obj.currentScanMode != WIFI_ATTACK_BEACON_SPAM) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_AP_SPAM) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_CSA) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_QUIET) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_AUTH) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH_MANUAL) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH_TARGETED) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_BAD_MSG_TARGETED) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_BAD_MSG) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_SLEEP) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_SLEEP_TARGETED) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_SAE_COMMIT) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_MIMIC) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_PACKET_RATE) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_RAW_CAPTURE) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_CHAN_ANALYZER) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_CHAN_ACT) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_SIG_STREN) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_AP) &&
+ (wifi_scan_obj.currentScanMode != BT_SCAN_FLOCK) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_PROBE) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_DEAUTH) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_FUNNY_BEACON) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_EAPOL) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_RICK_ROLL))
+ {
+ // Need this to set all keys to false
+ /*for (uint8_t b = 0; b < BUTTON_ARRAY_LEN; b++) {
+ if (pressed && display_obj.key[b].contains(t_x, t_y)) {
+ display_obj.key[b].press(true); // tell the button it is pressed
+ } else {
+ display_obj.key[b].press(false); // tell the button it is NOT pressed
+ }
+ }*/
+
+ // Detect up, down, select
+ uint8_t menu_button = display_obj.menuButton(&t_x, &t_y, pressed);
+
+ if (menu_button > -1) {
+ if (menu_button == UP_BUTTON) {
+ if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
+ (wifi_scan_obj.currentScanMode == WIFI_CONNECTED) ||
+ (wifi_scan_obj.currentScanMode == OTA_UPDATE)) {
+ if (current_menu->selected > 0) {
+ current_menu->selected--;
+ // Page up
+ if (current_menu->selected < this->menu_start_index) {
+ this->buildButtons(current_menu, current_menu->selected);
+ this->displayCurrentMenu(current_menu->selected);
+ }
+ this->buttonSelected(current_menu->selected - this->menu_start_index, current_menu->selected);
+ if (!current_menu->list->get(current_menu->selected + 1).selected || (current_menu->list->get(current_menu->selected + 1).icon == SETTINGS && current_menu->list->get(current_menu->selected + 1).color == TFTLIGHTGREY))
+ this->buttonNotSelected(current_menu->selected + 1 - this->menu_start_index, current_menu->selected + 1);
+ }
+ // Loop to end
+ else {
+ current_menu->selected = current_menu->list->size() - 1;
+ if (current_menu->selected >= BUTTON_SCREEN_LIMIT) {
+ this->buildButtons(current_menu, current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
+ this->displayCurrentMenu(current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
+ }
+ this->buttonSelected(current_menu->selected, current_menu->selected);
+ if (!current_menu->list->get(0).selected || (current_menu->list->get(0).icon == SETTINGS && current_menu->list->get(0).color == TFTLIGHTGREY))
+ this->buttonNotSelected(0, this->menu_start_index);
+ }
+ }
+ else if ((wifi_scan_obj.currentScanMode == WIFI_PACKET_MONITOR) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_EAPOL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PACKET_RATE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_RAW_CAPTURE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_DEAUTH) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN)) {
+ #ifndef HAS_DUAL_BAND
+ if (wifi_scan_obj.set_channel < 14)
+ wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel + 1);
+ else
+ wifi_scan_obj.changeChannel(1);
+ #else
+ if (wifi_scan_obj.dual_band_channel_index < DUAL_BAND_CHANNELS - 1)
+ wifi_scan_obj.dual_band_channel_index++;
+ else
+ wifi_scan_obj.dual_band_channel_index = 0;
+
+ wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
+ #endif
+ }
+ else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) {
+ #ifndef HAS_DUAL_BAND
+ if (wifi_scan_obj.activity_page < MAX_CHANNEL / CHAN_PER_PAGE) {
+ wifi_scan_obj.activity_page++;
+ }
+ #else
+ if (wifi_scan_obj.activity_page < DUAL_BAND_CHANNELS / CHAN_PER_PAGE) {
+ wifi_scan_obj.activity_page++;
+ }
+ #endif
+ wifi_scan_obj.drawChannelLine();
+ }
+ }
+ if (menu_button == DOWN_BUTTON) {
+ if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
+ (wifi_scan_obj.currentScanMode == WIFI_CONNECTED) ||
+ (wifi_scan_obj.currentScanMode == OTA_UPDATE)) {
+ if (current_menu->selected < current_menu->list->size() - 1) {
+ current_menu->selected++;
+ // Page down
+ if (current_menu->selected - this->menu_start_index >= BUTTON_SCREEN_LIMIT) {
+ this->buildButtons(current_menu, current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
+ this->displayCurrentMenu(current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
+ }
+ else
+ this->buttonSelected(current_menu->selected - this->menu_start_index, current_menu->selected);
+ if (!current_menu->list->get(current_menu->selected - 1).selected || (current_menu->list->get(current_menu->selected - 1).icon == SETTINGS && current_menu->list->get(current_menu->selected - 1).color == TFTLIGHTGREY))
+ this->buttonNotSelected(current_menu->selected - 1 - this->menu_start_index, current_menu->selected - 1);
+ }
+ // Loop to beginning
+ else {
+ if (current_menu->selected >= BUTTON_SCREEN_LIMIT) {
+ current_menu->selected = 0;
+ this->buildButtons(current_menu);
+ this->displayCurrentMenu();
+ this->buttonSelected(current_menu->selected);
+ }
+ else {
+ current_menu->selected = 0;
+ this->buttonSelected(current_menu->selected);
+ if (!current_menu->list->get(current_menu->list->size() - 1).selected || (current_menu->list->get(current_menu->list->size() - 1).icon == SETTINGS && current_menu->list->get(current_menu->list->size() - 1).color == TFTLIGHTGREY))
+ this->buttonNotSelected(current_menu->list->size() - 1);
+ }
+ }
+ }
+ else if ((wifi_scan_obj.currentScanMode == WIFI_PACKET_MONITOR) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_EAPOL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PACKET_RATE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_RAW_CAPTURE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_DEAUTH) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN)) {
+ #ifndef HAS_DUAL_BAND
+ if (wifi_scan_obj.set_channel > 1)
+ wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel - 1);
+ else
+ wifi_scan_obj.changeChannel(14);
+ #else
+ if (wifi_scan_obj.dual_band_channel_index > 0)
+ wifi_scan_obj.dual_band_channel_index--;
+ else
+ wifi_scan_obj.dual_band_channel_index = DUAL_BAND_CHANNELS - 1;
+
+ wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
+ #endif
+ }
+ else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) {
+ #ifndef HAS_DUAL_BAND
+ if (wifi_scan_obj.activity_page > 1) {
+ wifi_scan_obj.activity_page--;
+ }
+ #else
+ if (wifi_scan_obj.activity_page > 0) {
+ wifi_scan_obj.activity_page--;
+ }
+ #endif
+ wifi_scan_obj.drawChannelLine();
+ }
+ }
+ if(menu_button == SELECT_BUTTON) {
+ current_menu->list->get(current_menu->selected).callable();
+ }
+ else {
+ if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
+ (wifi_scan_obj.currentScanMode == WIFI_CONNECTED))
+ this->displayMenuButtons();
+ }
+ }
+ }
+ x = -1;
+ y = -1;
+ #endif
+
+ // Menu navigation and paging
+ #ifdef HAS_BUTTONS
+ // Don't do this for touch screens
+ #if !(defined(MARAUDER_V6) || defined(MARAUDER_V6_1) || defined(MARAUDER_CYD_MICRO) || defined(MARAUDER_CYD_GUITION) || defined(MARAUDER_CYD_2USB) || defined(MARAUDER_CYD_3_5_INCH))
+ #if !defined(MARAUDER_M5STICKC) || defined(MARAUDER_M5STICKCP2)
+ #if (U_BTN >= 0 || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV))
+ #if (U_BTN >= 0)
+ if (u_btn.justPressed()) {
+ #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+ if (this->isKeyPressed(';')) {
+ #endif
+ if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
+ (wifi_scan_obj.currentScanMode == WIFI_CONNECTED) ||
+ (wifi_scan_obj.currentScanMode == OTA_UPDATE)) {
+ if (current_menu->selected > 0) {
+ current_menu->selected--;
+ // Page up
+ if (current_menu->selected < this->menu_start_index) {
+ this->buildButtons(current_menu, current_menu->selected);
+ this->displayCurrentMenu(current_menu->selected);
+ }
+ this->buttonSelected(current_menu->selected - this->menu_start_index, current_menu->selected);
+ if (!current_menu->list->get(current_menu->selected + 1).selected || (current_menu->list->get(current_menu->selected + 1).icon == SETTINGS && current_menu->list->get(current_menu->selected + 1).color == TFTLIGHTGREY))
+ this->buttonNotSelected(current_menu->selected + 1 - this->menu_start_index, current_menu->selected + 1);
+ }
+ // Loop to end
+ else {
+ current_menu->selected = current_menu->list->size() - 1;
+ if (current_menu->selected >= BUTTON_SCREEN_LIMIT) {
+ this->buildButtons(current_menu, current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
+ this->displayCurrentMenu(current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
+ }
+ this->buttonSelected(current_menu->selected, current_menu->selected);
+ if (!current_menu->list->get(0).selected || (current_menu->list->get(0).icon == SETTINGS && current_menu->list->get(0).color == TFTLIGHTGREY))
+ this->buttonNotSelected(0, this->menu_start_index);
+ }
+ }
+ else if ((wifi_scan_obj.currentScanMode == WIFI_PACKET_MONITOR) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_EAPOL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PACKET_RATE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_RAW_CAPTURE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_DEAUTH) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN)) {
+ #ifndef HAS_DUAL_BAND
+ if (wifi_scan_obj.set_channel < 14)
+ wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel + 1);
+ else
+ wifi_scan_obj.changeChannel(1);
+ #else
+ if (wifi_scan_obj.dual_band_channel_index < DUAL_BAND_CHANNELS - 1)
+ wifi_scan_obj.dual_band_channel_index++;
+ else
+ wifi_scan_obj.dual_band_channel_index = 0;
+
+ wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
+ #endif
+ }
+ else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) {
+ #ifndef HAS_DUAL_BAND
+ if (wifi_scan_obj.activity_page < MAX_CHANNEL / CHAN_PER_PAGE) {
+ wifi_scan_obj.activity_page++;
+ }
+ #else
+ if (wifi_scan_obj.activity_page < DUAL_BAND_CHANNELS / CHAN_PER_PAGE) {
+ wifi_scan_obj.activity_page++;
+ }
+ #endif
+ wifi_scan_obj.drawChannelLine();
+ }
+ }
+ #endif
+ #endif
+
+ #if (D_BTN >= 0 || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV))
+ #if (D_BTN >= 0)
+ if (d_btn.justPressed()){
+ #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+ if (this->isKeyPressed('.')){
+ #endif
+ if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
+ (wifi_scan_obj.currentScanMode == WIFI_CONNECTED) ||
+ (wifi_scan_obj.currentScanMode == OTA_UPDATE)) {
+ if (current_menu->selected < current_menu->list->size() - 1) {
+ current_menu->selected++;
+ // Page down
+ if (current_menu->selected - this->menu_start_index >= BUTTON_SCREEN_LIMIT) {
+ this->buildButtons(current_menu, current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
+ this->displayCurrentMenu(current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
+ }
+ else
+ this->buttonSelected(current_menu->selected - this->menu_start_index, current_menu->selected);
+ if (!current_menu->list->get(current_menu->selected - 1).selected || (current_menu->list->get(current_menu->selected - 1).icon == SETTINGS && current_menu->list->get(current_menu->selected - 1).color == TFTLIGHTGREY))
+ this->buttonNotSelected(current_menu->selected - 1 - this->menu_start_index, current_menu->selected - 1);
+ }
+ // Loop to beginning
+ else {
+ if (current_menu->selected >= BUTTON_SCREEN_LIMIT) {
+ current_menu->selected = 0;
+ this->buildButtons(current_menu);
+ this->displayCurrentMenu();
+ this->buttonSelected(current_menu->selected);
+ }
+ else {
+ current_menu->selected = 0;
+ this->buttonSelected(current_menu->selected);
+ if (!current_menu->list->get(current_menu->list->size() - 1).selected || (current_menu->list->get(current_menu->list->size() - 1).icon == SETTINGS && current_menu->list->get(current_menu->list->size() - 1).color == TFTLIGHTGREY))
+ this->buttonNotSelected(current_menu->list->size() - 1);
+ }
+ }
+ }
+ else if ((wifi_scan_obj.currentScanMode == WIFI_PACKET_MONITOR) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_EAPOL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PACKET_RATE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_RAW_CAPTURE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_DEAUTH) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN)) {
+ #ifndef HAS_DUAL_BAND
+ if (wifi_scan_obj.set_channel > 1)
+ wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel - 1);
+ else
+ wifi_scan_obj.changeChannel(14);
+ #else
+ if (wifi_scan_obj.dual_band_channel_index > 0)
+ wifi_scan_obj.dual_band_channel_index--;
+ else
+ wifi_scan_obj.dual_band_channel_index = DUAL_BAND_CHANNELS - 1;
+
+ wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
+ #endif
+ }
+ else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) {
+ #ifndef HAS_DUAL_BAND
+ if (wifi_scan_obj.activity_page > 1) {
+ wifi_scan_obj.activity_page--;
+ }
+ #else
+ if (wifi_scan_obj.activity_page > 0) {
+ wifi_scan_obj.activity_page--;
+ }
+ #endif
+ wifi_scan_obj.drawChannelLine();
+ }
+ }
+ #endif
+
+ #if (R_BTN >= 0 || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV))
+ #if (R_BTN >= 0)
+ if (r_btn.justPressed()) {
+ #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+ if (this->isKeyPressed('/')) {
+ #endif
+ if (wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) {
+ #ifndef HAS_DUAL_BAND
+ if (wifi_scan_obj.set_channel < 14)
+ wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel + 1);
+ else
+ wifi_scan_obj.changeChannel(1);
+ #else
+ if (wifi_scan_obj.dual_band_channel_index < DUAL_BAND_CHANNELS - 1)
+ wifi_scan_obj.dual_band_channel_index++;
+ else
+ wifi_scan_obj.dual_band_channel_index = 0;
+
+ wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
+ #endif
+ }
+ }
+ #endif
+
+ #if (L_BTN >= 0 || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV))
+ #if (L_BTN >= 0)
+ if (l_btn.justPressed()) {
+ #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+ if (this->isKeyPressed(',')) {
+ #endif
+ if (wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) {
+ #ifndef HAS_DUAL_BAND
+ if (wifi_scan_obj.set_channel > 1)
+ wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel - 1);
+ else
+ wifi_scan_obj.changeChannel(14);
+ #else
+ if (wifi_scan_obj.dual_band_channel_index > 0)
+ wifi_scan_obj.dual_band_channel_index--;
+ else
+ wifi_scan_obj.dual_band_channel_index = DUAL_BAND_CHANNELS - 1;
+
+ wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
+ #endif
+ }
+ }
+ #endif
+
+ #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+ if (this->isKeyPressed('`') || this->isKeyPressed(KEY_BACKSPACE)) {
+ if (wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) {
+ if (current_menu->parentMenu != NULL) {
+ this->changeMenu(current_menu->parentMenu, true);
+ }
+ }
+ }
+ #endif
+
+ if(c_btn_press){
+ current_menu->list->get(current_menu->selected).callable();
+ }
+
+ #endif
+ #endif
+}
+
+#if BATTERY_ANALOG_ON == 1
+byte battery_analog_array[10];
+byte battery_count = 0;
+byte battery_analog_last = 101;
+#define BATTERY_CHECK 50
+uint16_t battery_analog = 0;
+void MenuFunctions::battery(bool initial)
+{
+ if (BATTERY_ANALOG_ON) {
+ uint8_t n = 0;
+ byte battery_analog_sample[10];
+ byte deviation;
+ if (battery_count == BATTERY_CHECK - 5) digitalWrite(BATTERY_PIN, HIGH);
+ else if (battery_count == 5) digitalWrite(BATTERY_PIN, LOW);
+ if (battery_count == 0) {
+ battery_analog = 0;
+ for (n = 9; n > 0; n--)battery_analog_array[n] = battery_analog_array[n - 1];
+ for (n = 0; n < 10; n++) {
+ battery_analog_sample[n] = map((analogRead(ANALOG_PIN) * 5), 2400, 4200, 0, 100);
+ if (battery_analog_sample[n] > 100) battery_analog_sample[n] = 100;
+ else if (battery_analog_sample[n] < 0) battery_analog_sample[n] = 0;
+ battery_analog += battery_analog_sample[n];
+ }
+ battery_analog = battery_analog / 10;
+ for (n = 0; n < 10; n++) {
+ deviation = abs(battery_analog - battery_analog_sample[n]);
+ if (deviation >= 10) battery_analog_sample[n] = battery_analog;
+ }
+ battery_analog = 0;
+ for (n = 0; n < 10; n++) battery_analog += battery_analog_sample[n];
+ battery_analog = battery_analog / 10;
+ battery_analog_array[0] = battery_analog;
+ if (battery_analog_array[9] > 0 ) {
+ battery_analog = 0;
+ for (n = 0; n < 10; n++) battery_analog += battery_analog_array[n];
+ battery_analog = battery_analog / 10;
+ }
+ battery_count ++;
+ }
+ else if (battery_count < BATTERY_CHECK) battery_count++;
+ else if (battery_count >= BATTERY_CHECK) battery_count = 0;
+
+ if (battery_analog_last != battery_analog) {
+ battery_analog_last = battery_analog;
+ MenuFunctions::battery2();
+ }
+ }
+}
+void MenuFunctions::battery2(bool initial)
+{
+ uint16_t the_color;
+ if ( digitalRead(CHARGING_PIN) == 1) the_color = TFT_BLUE;
+ else if (battery_analog < 20) the_color = TFT_RED;
+ else if (battery_analog < 40) the_color = TFT_YELLOW;
+ else the_color = TFT_GREEN;
+
+ display_obj.tft.setTextColor(the_color, STATUSBAR_COLOR);
+ display_obj.tft.fillRect(SB_TOUCH_X, 0, 50, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+ display_obj.tft.drawXBitmap(SB_TOUCH_X,
+ 0,
+ menu_icons[STATUS_BAT],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ the_color);
+ display_obj.tft.drawString((String) battery_analog + "%", SB_BAT_X, 0, 2);
+}
+#else
+void MenuFunctions::battery(bool initial)
+{
+ #ifdef HAS_BATTERY
+ uint16_t the_color;
+ if (battery_obj.i2c_supported)
+ {
+ // Could use int compare maybe idk
+ if (((String)battery_obj.battery_level != "25") && ((String)battery_obj.battery_level != "0"))
+ the_color = TFT_GREEN;
+ else
+ the_color = TFT_RED;
+
+ if ((battery_obj.battery_level != battery_obj.old_level) || (initial)) {
+ battery_obj.old_level = battery_obj.battery_level;
+ display_obj.tft.fillRect(204, 0, SCREEN_WIDTH, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+ }
+
+ display_obj.tft.setCursor(0, 1);
+ /*if (!this->disable_touch) {
+ display_obj.tft.drawXBitmap(SB_TOUCH_X,
+ 0,
+ menu_icons[STATUS_BAT],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ the_color);
+ }*/
+ #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+ display_obj.tft.drawString((String)battery_obj.battery_level + "%", SB_BAT_X, 0, 1);
+ #else
+ display_obj.tft.drawString((String)battery_obj.battery_level + "%", SB_BAT_X, 0, 2);
+ #endif
+ }
+ #endif
+}
+void MenuFunctions::battery2(bool initial)
+{
+ MenuFunctions::battery(initial);
+}
+#endif
+
+void MenuFunctions::updateStatusBar()
+{
+ display_obj.tft.setTextSize(1);
+
+ bool status_changed = false;
+
+ #if defined(MARAUDER_MINI) || defined(MARAUDER_M5STICKC) || defined(MARAUDER_REV_FEATHER) || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) || defined(MARAUDER_MINI_V3)
+ display_obj.tft.setFreeFont(NULL);
+ #endif
+
+ uint16_t the_color;
+
+ #ifdef HAS_GPS
+ if (this->old_gps_sat_count != gps_obj.getNumSats()) {
+ this->old_gps_sat_count = gps_obj.getNumSats();
+ display_obj.tft.fillRect(0, 0, SCREEN_WIDTH, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+ status_changed = true;
+ }
+ #endif
+
+ // GPS Stuff
+ #ifdef HAS_GPS
+ if (gps_obj.getGpsModuleStatus()) {
+ if (gps_obj.getFixStatus())
+ the_color = TFT_GREEN;
+ else
+ the_color = TFT_RED;
+
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(4,
+ 0,
+ menu_icons[STATUS_GPS],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ the_color);
+ display_obj.tft.setTextColor(TFT_WHITE, STATUSBAR_COLOR, true);
+
+ display_obj.tft.drawString(gps_obj.getNumSatsString(), 22, 0, 2);
+ #elif defined(HAS_SCREEN)
+ display_obj.tft.setTextColor(the_color, STATUSBAR_COLOR, true);
+ display_obj.tft.drawString("GPS", 0, 0, 1);
+ #endif
+ }
+ #endif
+
+ display_obj.tft.setTextColor(TFT_WHITE, STATUSBAR_COLOR, true);
+
+ // WiFi Channel Stuff
+ uint8_t primaryChannel;
+ wifi_second_chan_t secondChannel;
+ esp_err_t err = esp_wifi_get_channel(&primaryChannel, &secondChannel);
+
+ uint8_t current_channel = wifi_scan_obj.set_channel;
+
+ if (err == ESP_OK)
+ current_channel = primaryChannel;
+
+ if ((current_channel != wifi_scan_obj.old_channel) || (status_changed)) {
+ wifi_scan_obj.old_channel = current_channel;
+ #if defined(MARAUDER_MINI) || defined(MARAUDER_M5STICKC) || defined(MARAUDER_REV_FEATHER) || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) || defined(MARAUDER_MINI_V3)
+ display_obj.tft.fillRect(TFT_WIDTH/4, 0, CHAR_WIDTH * 6, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+ #elif defined(HAS_DUAL_BAND)
+ display_obj.tft.fillRect(50, 0, (CHAR_WIDTH / 2) * 8, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+ #else
+ display_obj.tft.fillRect(50, 0, (CHAR_WIDTH / 2) * 7, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+ #endif
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawString("CH: " + (String)wifi_scan_obj.old_channel, 50, 0, 2);
+ #endif
+
+ #ifdef HAS_MINI_SCREEN
+ display_obj.tft.drawString("CH:" + (String)wifi_scan_obj.old_channel, TFT_WIDTH/4, 0, 1);
+ #endif
+ }
+
+ // RAM Stuff
+ wifi_scan_obj.free_ram = String(esp_get_free_heap_size());
+ if ((wifi_scan_obj.free_ram != wifi_scan_obj.old_free_ram) || (status_changed)) {
+ wifi_scan_obj.old_free_ram = wifi_scan_obj.free_ram;
+ //display_obj.tft.fillRect(SB_MEM_X, 0, 60, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+ #ifdef HAS_FULL_SCREEN
+ #ifndef HAS_PSRAM
+ display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", SB_MEM_X, 0, 2);
+ #else
+ display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", SB_MEM_X, 0, 1);
+ display_obj.tft.drawString("P:" + String(getPSRAMUsagePercent()) + "%", SB_MEM_X, 8, 1);
+ #endif
+ #endif
+
+ #ifdef HAS_MINI_SCREEN
+ display_obj.tft.drawString(String(getDRAMUsagePercent()) + "%", TFT_WIDTH/1.75, 0, 1);
+ #endif
+ }
+
+ // Draw battery info
+ MenuFunctions::battery(false);
+ display_obj.tft.fillRect(186, 0, 16, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+
+ // Disable touch stuff
+ #ifdef HAS_ILI9341
+ #ifdef HAS_BUTTONS
+ if (this->disable_touch) {
+ display_obj.tft.setCursor(0, 1);
+ display_obj.tft.drawXBitmap(SB_TOUCH_X,
+ 0,
+ menu_icons[DISABLE_TOUCH],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_RED);
+ }
+ else {
+ display_obj.tft.setCursor(0, 1);
+ display_obj.tft.drawXBitmap(SB_TOUCH_X,
+ 0,
+ menu_icons[DISABLE_TOUCH],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_DARKGREY);
+ }
+ #endif
+ #endif
+
+ // Draw SD info
+ #ifdef HAS_SD
+ if (sd_obj.supported)
+ the_color = TFT_GREEN;
+ else
+ the_color = TFT_RED;
+
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(SB_SD_X,
+ 0,
+ menu_icons[STATUS_SD],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ the_color);
+ #endif
+ #endif
+
+ #ifdef HAS_MINI_SCREEN
+ display_obj.tft.setTextColor(the_color, STATUSBAR_COLOR, true);
+ display_obj.tft.drawString("SD", TFT_WIDTH - 12, 0, 1);
+ #endif
+
+ // WiFi connection status stuff
+ if (wifi_scan_obj.wifi_connected) {
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(SB_WIFI_X,
+ 0,
+ menu_icons[JOINED],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_GREEN);
+ #endif
+ } else {
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(SB_WIFI_X,
+ 0,
+ menu_icons[JOINED],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_DARKGREY);
+ #endif
+ }
+
+ // Force PMKID stuff
+ if ((wifi_scan_obj.force_pmkid) || (wifi_scan_obj.ep_deauth)) {
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(SB_FORCE_X,
+ 0,
+ menu_icons[FORCE],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_GREEN);
+ #endif
+ } else {
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(SB_FORCE_X,
+ 0,
+ menu_icons[FORCE],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_DARKGREY);
+ #endif
+ }
+}
+
+void MenuFunctions::drawStatusBar()
+{
+ display_obj.tft.setTextSize(1);
+ #ifdef HAS_MINI_SCREEN
+ display_obj.tft.setFreeFont(NULL);
+ #endif
+ display_obj.tft.fillRect(0, 0, SCREEN_WIDTH, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+ display_obj.tft.setTextColor(TFT_WHITE, STATUSBAR_COLOR);
+
+ uint16_t the_color;
+
+ // GPS Stuff
+ #ifdef HAS_GPS
+ if (gps_obj.getGpsModuleStatus()) {
+ if (gps_obj.getFixStatus())
+ the_color = TFT_GREEN;
+ else
+ the_color = TFT_RED;
+
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(4,
+ 0,
+ menu_icons[STATUS_GPS],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ the_color);
+ display_obj.tft.setTextColor(TFT_WHITE, STATUSBAR_COLOR);
+
+ display_obj.tft.drawString(gps_obj.getNumSatsString(), 22, 0, 2);
+ #endif
+ }
+ #endif
+
+ display_obj.tft.setTextColor(TFT_WHITE, STATUSBAR_COLOR);
+
+
+ // WiFi Channel Stuff
+ uint8_t primaryChannel;
+ wifi_second_chan_t secondChannel;
+ esp_err_t err = esp_wifi_get_channel(&primaryChannel, &secondChannel);
+
+ if (err == ESP_OK)
+ wifi_scan_obj.old_channel = primaryChannel;
+ else
+ wifi_scan_obj.old_channel = wifi_scan_obj.set_channel;
+
+ #ifdef HAS_MINI_SCREEN
+ display_obj.tft.fillRect(43, 0, TFT_WIDTH * 0.21, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+ #else
+ display_obj.tft.fillRect(50, 0, TFT_WIDTH * 0.21, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+ #endif
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawString("CH: " + (String)wifi_scan_obj.old_channel, 50, 0, 2);
+ #endif
+
+ #ifdef HAS_MINI_SCREEN
+ display_obj.tft.drawString("CH:" + (String)wifi_scan_obj.old_channel, TFT_WIDTH/4, 0, 1);
+ #endif
+
+ // RAM Stuff
+ wifi_scan_obj.free_ram = String(esp_get_free_heap_size());
+ wifi_scan_obj.old_free_ram = wifi_scan_obj.free_ram;
+ display_obj.tft.fillRect(100, 0, 60, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+ #ifdef HAS_FULL_SCREEN
+ #ifndef HAS_PSRAM
+ display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", SB_MEM_X, 0, 2);
+ #else
+ display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", SB_MEM_X, 0, 1);
+ display_obj.tft.drawString("P:" + String(getPSRAMUsagePercent()) + "%", SB_MEM_X, 8, 1);
+ #endif
+ #endif
+
+ #ifdef HAS_MINI_SCREEN
+ display_obj.tft.drawString(String(getDRAMUsagePercent()) + "%", TFT_WIDTH/1.75, 0, 1);
+ #endif
+
+
+ MenuFunctions::battery(true);
+ display_obj.tft.fillRect(186, 0, 16, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+
+
+ // Disable touch stuff
+ #ifdef HAS_ILI9341
+ #ifdef HAS_BUTTONS
+ if (this->disable_touch) {
+ display_obj.tft.setCursor(0, 1);
+ display_obj.tft.drawXBitmap(SB_TOUCH_X,
+ 0,
+ menu_icons[DISABLE_TOUCH],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_RED);
+ }
+ else {
+ display_obj.tft.setCursor(0, 1);
+ display_obj.tft.drawXBitmap(SB_TOUCH_X,
+ 0,
+ menu_icons[DISABLE_TOUCH],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_DARKGREY);
+ }
+ #endif
+ #endif
+
+ // Draw SD info
+ #ifdef HAS_SD
+ if (sd_obj.supported)
+ the_color = TFT_GREEN;
+ else
+ the_color = TFT_RED;
+
+
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(SB_SD_X,
+ 0,
+ menu_icons[STATUS_SD],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ the_color);
+ #endif
+ #endif
+
+ #ifdef HAS_MINI_SCREEN
+ display_obj.tft.setTextColor(the_color, STATUSBAR_COLOR);
+ display_obj.tft.drawString("SD", TFT_WIDTH - 12, 0, 1);
+ #endif
+
+ // WiFi connection status stuff
+ if (wifi_scan_obj.wifi_connected) {
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(SB_WIFI_X,
+ 0,
+ menu_icons[JOINED],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_GREEN);
+ #endif
+ } else {
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(SB_WIFI_X,
+ 0,
+ menu_icons[JOINED],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_DARKGREY);
+ #endif
+ }
+
+ // Force PMKID stuff
+ if ((wifi_scan_obj.force_pmkid) || (wifi_scan_obj.ep_deauth)) {
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(SB_FORCE_X,
+ 0,
+ menu_icons[FORCE],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_GREEN);
+ #endif
+ } else {
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(SB_FORCE_X,
+ 0,
+ menu_icons[FORCE],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_DARKGREY);
+ #endif
+ }
+}
+
+void MenuFunctions::orientDisplay() {
+ display_obj.init();
+
+ display_obj.tft.setRotation(SCREEN_ORIENTATION); // Portrait
+
+ display_obj.tft.setCursor(0, 0);
+
+ #ifdef HAS_ILI9341
+ #ifndef HAS_CYD_TOUCH
+ display_obj.setCalData();
+ #else
+ display_obj.touchscreen.setRotation(0);
+ #endif
+ #endif
+
+ changeMenu(current_menu, true);
+}
+
+const char* MenuFunctions::callSetting(const char* key) {
+ specSettingMenu.name = key;
+
+ const char* setting_type = settings_obj.getSettingType(key);
+
+ if (setting_type && strcmp(setting_type, "bool") == 0) {
+ return "bool";
+ }
+
+ return "";
+}
+
+/*void MenuFunctions::displaySetting(String key, Menu* menu, int index) {
+ specSettingMenu.name = key;
+
+ bool setting_value = settings_obj.loadSetting(key);
+
+ // Make a local copy of menu node
+ MenuNode node = menu->list->get(index);
+
+ display_obj.tft.setTextWrap(false);
+ display_obj.tft.setFreeFont(NULL);
+ display_obj.tft.setCursor(0, 100);
+ display_obj.tft.setTextSize(1);
+
+ // Set local copy value
+ if (!setting_value) {
+ display_obj.tft.setTextColor(TFT_RED);
+ display_obj.tft.println(F(text_table1[4]));
+ node.selected = false;
+ }
+ else {
+ display_obj.tft.setTextColor(TFT_GREEN);
+ display_obj.tft.println(F(text_table1[5]));
+ node.selected = true;
+ }
+
+ // Put local copy back into menu
+ menu->list->set(index, node);
+
+}*/
+
+void MenuFunctions::displaySetting(const char* key, Menu* menu, int index) {
+ specSettingMenu.name = String(key);
+
+ bool setting_value = settings_obj.loadSetting(key);
+
+ // Make a local copy of menu node
+ MenuNode node = menu->list->get(index);
+
+ display_obj.tft.setTextWrap(false);
+ display_obj.tft.setFreeFont(NULL);
+ display_obj.tft.setCursor(0, 100);
+ display_obj.tft.setTextSize(1);
+
+ // Set local copy value
+ if (!setting_value) {
+ display_obj.tft.setTextColor(TFT_RED);
+ display_obj.tft.println(F(text_table1[4]));
+ node.selected = false;
+ } else {
+ display_obj.tft.setTextColor(TFT_GREEN);
+ display_obj.tft.println(F(text_table1[5]));
+ node.selected = true;
+ }
+
+ // Put local copy back into menu
+ menu->list->set(index, node);
+}
+
+#if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+void MenuFunctions::updateKeyboard()
+{
+ M5CardputerKeyboard.updateKeyList();
+ M5CardputerKeyboard.updateKeysState();
+}
+
+bool MenuFunctions::isKeyPressed(char c)
+{
+ bool pressed = M5CardputerKeyboard.isKeyPressed(c);
+
+ if (pressed)
+ delay(200);
+
+ return pressed;
+}
+#endif
+
+#ifdef HAS_DIRECT_UPLOAD
+ void MenuFunctions::buildUploadFileMenu() {
+ if (sd_obj.supported) {
+ this->setupSDFileList();
+
+ uploadLogsMenu.list->clear();
+ delete uploadLogsMenu.list;
+ uploadLogsMenu.list = new LinkedList();
+ uploadLogsMenu.name = "Logs";
+
+ uploadLogsMenu.parentMenu = &wifiGeneralMenu;
+
+ this->addNodes(&uploadLogsMenu, "Back", TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(uploadLogsMenu.parentMenu, true);
+ });
+
+ this->addNodes(&uploadLogsMenu, "Delete Wardrive Logs", TFTORANGE, 0, [this]() {
+ this->changeMenu(&deleteAllMenu, true);
+ });
+
+ this->addNodes(&uploadLogsMenu, "Upload All", TFTGREEN, 0, [this]() {
+ this->changeMenu(&uploadAllMenu, true);
+
+ });
+
+ for (int i = 0; i < sd_obj.sd_files->size(); i++) {
+ File current_file = sd_obj.getFile("/" + sd_obj.sd_files->get(i));
+ if (sd_obj.sd_files->get(i).startsWith("wardrive_") || sd_obj.sd_files->get(i).startsWith("wigle-")) {
+ if (!sd_obj.sd_files->get(i).endsWith(".wdg") && !sd_obj.sd_files->get(i).endsWith(".wigle") && !sd_obj.sd_files->get(i).endsWith(".gpx")) {
+ this->addNodes(&uploadLogsMenu, sd_obj.sd_files->get(i).c_str(), TFTCYAN, 0, [this, i]() {
+ sd_obj.selected_file_name = sd_obj.sd_files->get(i);
+ Serial.println(sd_obj.sd_files->get(i) + " selected");
+ this->changeMenu(&actionMenu, true);
+ });
+ }
+ }
+ }
+
+ Serial.println("Built SD file menu with " + (String)sd_obj.sd_files->size() + " files");
+ } else {
+ Serial.println("SD Card not detected. Skipping menu creation...");
+ }
+ }
#endif
const char* MenuFunctions::foxSortLabel() const {
@@ -1786,2878 +1786,2878 @@ void MenuFunctions::buildBluetoothFoxHuntMenu() {
// Function to build the menus
void MenuFunctions::RunSetup()
-{
- extern LinkedList* access_points;
- extern LinkedList* stations;
- extern LinkedList* airtags;
- extern LinkedList* ipList;
- extern LinkedList* probe_req_ssids;
- extern LinkedList* ssids;
- extern LinkedList* ble_devices;
-
- this->disable_touch = false;
-
- #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
- M5CardputerKeyboard.begin();
- #endif
-
- // root menu stuff
- mainMenu.list = new LinkedList(); // Get list in first menu ready
-
- // Main menu stuff
- wifiMenu.list = new LinkedList(); // Get list in second menu ready
-#ifdef HAS_BT
- bluetoothMenu.list = new LinkedList(); // Get list in third menu ready
-#endif
- deviceMenu.list = new LinkedList();
- #ifdef HAS_GPS
- if (gps_obj.getGpsModuleStatus()) {
- gpsMenu.list = new LinkedList();
- gpsInfoMenu.list = new LinkedList();
- }
- #endif
-
- // Device menu stuff
- failedUpdateMenu.list = new LinkedList();
- confirmMenu.list = new LinkedList();
- updateMenu.list = new LinkedList();
- settingsMenu.list = new LinkedList();
- specSettingMenu.list = new LinkedList();
- infoMenu.list = new LinkedList();
- // WiFi menu stuff
- wifiSnifferMenu.list = new LinkedList();
- wifiScannerMenu.list = new LinkedList();
- wifiAttackMenu.list = new LinkedList();
- /*#ifdef HAS_GPS
- wardrivingMenu.list = new LinkedList();
- #endif*/
- wifiGeneralMenu.list = new LinkedList();
- wifiAPMenu.list = new LinkedList();
- wifiIPMenu.list = new LinkedList();
- apInfoMenu.list = new LinkedList();
- setMacMenu.list = new LinkedList();
- genAPMacMenu.list = new LinkedList();
+{
+ extern LinkedList* access_points;
+ extern LinkedList* stations;
+ extern LinkedList* airtags;
+ extern LinkedList* ipList;
+ extern LinkedList* probe_req_ssids;
+ extern LinkedList* ssids;
+ extern LinkedList* ble_devices;
+
+ this->disable_touch = false;
+
+ #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+ M5CardputerKeyboard.begin();
+ #endif
+
+ // root menu stuff
+ mainMenu.list = new LinkedList(); // Get list in first menu ready
+
+ // Main menu stuff
+ wifiMenu.list = new LinkedList(); // Get list in second menu ready
+#ifdef HAS_BT
+ bluetoothMenu.list = new LinkedList(); // Get list in third menu ready
+#endif
+ deviceMenu.list = new LinkedList();
+ #ifdef HAS_GPS
+ if (gps_obj.getGpsModuleStatus()) {
+ gpsMenu.list = new LinkedList();
+ gpsInfoMenu.list = new LinkedList();
+ }
+ #endif
+
+ // Device menu stuff
+ failedUpdateMenu.list = new LinkedList();
+ confirmMenu.list = new LinkedList();
+ updateMenu.list = new LinkedList();
+ settingsMenu.list = new LinkedList();
+ specSettingMenu.list = new LinkedList();
+ infoMenu.list = new LinkedList();
+ // WiFi menu stuff
+ wifiSnifferMenu.list = new LinkedList();
+ wifiScannerMenu.list = new LinkedList();
+ wifiAttackMenu.list = new LinkedList();
+ /*#ifdef HAS_GPS
+ wardrivingMenu.list = new LinkedList();
+ #endif*/
+ wifiGeneralMenu.list = new LinkedList();
+ wifiAPMenu.list = new LinkedList();
+ wifiIPMenu.list = new LinkedList();
+ apInfoMenu.list = new LinkedList();
+ setMacMenu.list = new LinkedList();
+ genAPMacMenu.list = new LinkedList();
wifiStationMenu.list = new LinkedList();
foxSortMenu.list = new LinkedList();
foxFilterMenu.list = new LinkedList();
- selectProbeSSIDsMenu.list = new LinkedList();
-
- // WiFi HTML menu stuff
- htmlMenu.list = new LinkedList();
- miniKbMenu.list = new LinkedList();
- #ifdef HAS_SD
- sdDeleteMenu.list = new LinkedList();
- #endif
-
- // Bluetooth menu stuff
- bluetoothSnifferMenu.list = new LinkedList();
- bluetoothAttackMenu.list = new LinkedList();
-
- // Settings stuff
- generateSSIDsMenu.list = new LinkedList();
- clearSSIDsMenu.list = new LinkedList();
- clearAPsMenu.list = new LinkedList();
- saveFileMenu.list = new LinkedList();
-
- #ifdef HAS_DIRECT_UPLOAD
- uploadLogsMenu.list = new LinkedList();
- uploadAllMenu.list = new LinkedList();
- deleteAllMenu.list = new LinkedList();
- actionMenu.list = new LinkedList();
- #endif
-
- saveSSIDsMenu.list = new LinkedList();
- loadSSIDsMenu.list = new LinkedList();
- saveAPsMenu.list = new LinkedList();
- loadAPsMenu.list = new LinkedList();
- saveATsMenu.list = new LinkedList();
- loadATsMenu.list = new LinkedList();
-
- evilPortalMenu.list = new LinkedList();
- ssidsMenu.list = new LinkedList();
-
- #ifdef HAS_GPS
- gpsPOIMenu.list = new LinkedList();
- #endif
-
- foxHuntMenu.list = new LinkedList();
-
- // Work menu names
- mainMenu.name = text_table1[6];
- wifiMenu.name = text_table1[7];
- deviceMenu.name = text_table1[9];
- failedUpdateMenu.name = text_table1[11];
- confirmMenu.name = text_table1[13];
- updateMenu.name = text_table1[15];
- infoMenu.name = text_table1[17];
- settingsMenu.name = text_table1[18];
- bluetoothMenu.name = text_table1[19];
- wifiSnifferMenu.name = text_table1[20];
- wifiScannerMenu.name = "Scanners";
- wifiAttackMenu.name = text_table1[21];
- wifiGeneralMenu.name = text_table1[22];
- saveFileMenu.name = "Save/Load Files";
- saveSSIDsMenu.name = "Save SSIDs";
- loadSSIDsMenu.name = "Load SSIDs";
- saveAPsMenu.name = "Save APs";
- loadAPsMenu.name = "Load APs";
- saveATsMenu.name = "Save Airtags";
- loadATsMenu.name = "Load Airtags";
-
- bluetoothSnifferMenu.name = text_table1[23];
- bluetoothAttackMenu.name = "Bluetooth Attacks";
- generateSSIDsMenu.name = text_table1[27];
- clearSSIDsMenu.name = text_table1[28];
- clearAPsMenu.name = text_table1[29];
- wifiAPMenu.name = "Select";
- wifiIPMenu.name = "Active IPs";
- apInfoMenu.name = "AP Info";
- setMacMenu.name = "Set MACs";
- genAPMacMenu.name = "Generate AP MAC";
- wifiStationMenu.name = "Select Stations";
-
- #ifdef HAS_DIRECT_UPLOAD
- uploadLogsMenu.name = "Upload Logs";
- uploadAllMenu.name = "Upload All?";
- deleteAllMenu.name = "Delete All?";
- actionMenu.name = "Destination";
- #endif
-
- #ifdef HAS_GPS
- gpsMenu.name = "GPS";
- gpsInfoMenu.name = "GPS Data";
- //wardrivingMenu.name = "Wardriving";
- #endif
- htmlMenu.name = "EP HTML List";
- miniKbMenu.name = "Mini Keyboard";
-
- #ifdef HAS_SD
- sdDeleteMenu.name = "Delete SD Files";
- #endif
-
- selectProbeSSIDsMenu.name = "Probe Requests";
- evilPortalMenu.name = "Evil Portal";
- ssidsMenu.name = "SSIDs";
-
- #ifdef HAS_GPS
- gpsPOIMenu.name = "GPS POI";
- #endif
-
- foxHuntMenu.name = "Fox Hunt";
-
- // Build Main Menu
- mainMenu.parentMenu = NULL;
- this->addNodes(&mainMenu, text_table1[7], TFTGREEN, WIFI, [this]() {
- this->changeMenu(&wifiMenu, true);
- });
- #ifdef HAS_BT
- this->addNodes(&mainMenu, text_table1[19], TFTCYAN, BLUETOOTH, [this]() {
- this->changeMenu(&bluetoothMenu, true);
- });
- #endif
- #ifdef HAS_GPS
- if (gps_obj.getGpsModuleStatus()) {
- this->addNodes(&mainMenu, text1_66, TFTRED, GPS_MENU, [this]() {
- this->changeMenu(&gpsMenu, true);
- });
- }
- #endif
- this->addNodes(&mainMenu, text_table1[9], TFTBLUE, DEVICE, [this]() {
- this->changeMenu(&deviceMenu, true);
- });
- this->addNodes(&mainMenu, text_table1[30], TFTLIGHTGREY, REBOOT, []() {
- ESP.restart();
- });
-
- // Build WiFi Menu
- wifiMenu.parentMenu = &mainMenu; // Main Menu is second menu parent
- this->addNodes(&wifiMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(wifiMenu.parentMenu, true);
- });
- this->addNodes(&wifiMenu, text_table1[31], TFTYELLOW, SNIFFERS, [this]() {
- this->changeMenu(&wifiSnifferMenu, true);
- });
- this->addNodes(&wifiMenu, "Scanners", TFTORANGE, SCANNERS, [this]() {
- this->changeMenu(&wifiScannerMenu, true);
- });
- /*#ifdef HAS_GPS
- this->addNodes(&wifiMenu, "Wardriving", TFTGREEN, NULL, BEACON_SNIFF, [this]() {
- this->changeMenu(&wardrivingMenu, true);
- });
- #endif*/
- this->addNodes(&wifiMenu, text_table1[32], TFTRED, ATTACKS, [this]() {
- this->changeMenu(&wifiAttackMenu, true);
- });
- this->addNodes(&wifiMenu, text_table1[33], TFTPURPLE, GENERAL_APPS, [this]() {
- this->changeMenu(&wifiGeneralMenu, true);
- });
-
- // Build WiFi scanner Menu
- wifiScannerMenu.parentMenu = &wifiMenu; // Main Menu is second menu parent
- this->addNodes(&wifiScannerMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(wifiScannerMenu.parentMenu, true);
- });
- this->addNodes(&wifiScannerMenu, "Ping Scan", TFTGREEN, SCANNERS, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_PING_SCAN, TFT_CYAN);
- });
- // GCOVR_EXCL_START -- scanner menu wiring requires the hardware UI.
- this->addNodes(&wifiScannerMenu, "ARP Scan", TFTCYAN, SCANNERS, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_ARP_SCAN, TFT_CYAN);
- });
- // GCOVR_EXCL_STOP
- this->addNodes(&wifiScannerMenu, "Port Scan All", TFTMAGENTA, BEACON_LIST, [this](){
- // Add the back button
- wifiIPMenu.list->clear();
- this->addNodes(&wifiIPMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(wifiIPMenu.parentMenu, true);
- });
-
- // Populate the menu with buttons
- for (int i = 0; i < ipList->size(); i++) {
- // This is the menu node
- this->addNodes(&wifiIPMenu, ipList->get(i).toString().c_str(), TFTBLUE, 255, [this, i](){
- Serial.println("Selected: " + ipList->get(i).toString());
- wifi_scan_obj.current_scan_ip = ipList->get(i);
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_PORT_SCAN_ALL, TFT_BLUE);
- });
- }
- this->changeMenu(&wifiIPMenu, true);
- });
- this->addNodes(&wifiScannerMenu, "SSH Scan", TFTORANGE, SCANNERS, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_SSH, TFT_CYAN);
- });
- this->addNodes(&wifiScannerMenu, "Telnet Scan", TFTRED, SCANNERS, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_TELNET, TFT_CYAN);
- });
- this->addNodes(&wifiScannerMenu, "SMTP Scan", TFTWHITE, SCANNERS, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_SMTP, TFT_CYAN);
- });
- this->addNodes(&wifiScannerMenu, "DNS Scan", TFTLIME, SCANNERS, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_DNS, TFT_CYAN);
- });
- this->addNodes(&wifiScannerMenu, "HTTP Scan", TFTSKYBLUE, SCANNERS, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_HTTP, TFT_CYAN);
- });
- this->addNodes(&wifiScannerMenu, "HTTPS Scan", TFTYELLOW, SCANNERS, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_HTTPS, TFT_CYAN);
- });
- this->addNodes(&wifiScannerMenu, "RDP Scan", TFTPURPLE, SCANNERS, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_RDP, TFT_CYAN);
- });
-
- // Build WiFi sniffer Menu
- wifiSnifferMenu.parentMenu = &wifiMenu; // Main Menu is second menu parent
- this->addNodes(&wifiSnifferMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(wifiSnifferMenu.parentMenu, true);
- });
- this->addNodes(&wifiSnifferMenu, text_table1[42], TFTCYAN, PROBE_SNIFF, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_PROBE, TFT_CYAN);
- });
- this->addNodes(&wifiSnifferMenu, text_table1[43], TFTMAGENTA, BEACON_SNIFF, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_AP, TFT_MAGENTA);
- });
- this->addNodes(&wifiSnifferMenu, text_table1[44], TFTRED, DEAUTH_SNIFF, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_DEAUTH, TFT_RED);
- });
- this->addNodes(&wifiSnifferMenu, "Packet Count", TFTORANGE, PACKET_MONITOR, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_PACKET_RATE, TFT_ORANGE);
- wifi_scan_obj.renderPacketRate();
- });
- #ifdef HAS_ILI9341
- this->addNodes(&wifiSnifferMenu, text_table1[46], TFTVIOLET, EAPOL, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_EAPOL, TFT_VIOLET);
- });
- this->addNodes(&wifiSnifferMenu, text_table1[45], TFTBLUE, PACKET_MONITOR, [this]() {
- wifi_scan_obj.StartScan(WIFI_PACKET_MONITOR, TFT_BLUE);
- });
- #else // No touch
- this->addNodes(&wifiSnifferMenu, text_table1[46], TFTVIOLET, EAPOL, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_EAPOL, TFT_VIOLET);
- });
- this->addNodes(&wifiSnifferMenu, text_table1[45], TFTBLUE, PACKET_MONITOR, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_PACKET_MONITOR, TFT_BLUE);
- });
- #endif
- this->addNodes(&wifiSnifferMenu, "Channel Analyzer", TFTCYAN, PACKET_MONITOR, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- this->renderGraphUI(WIFI_SCAN_CHAN_ANALYZER);
- wifi_scan_obj.StartScan(WIFI_SCAN_CHAN_ANALYZER, TFT_CYAN);
- });
- this->addNodes(&wifiSnifferMenu, "Channel Summary", TFTORANGE, PACKET_MONITOR, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- this->renderGraphUI(WIFI_SCAN_CHAN_ACT);
- wifi_scan_obj.StartScan(WIFI_SCAN_CHAN_ACT, TFT_CYAN);
- });
-
- this->addNodes(&wifiSnifferMenu, text_table1[58], TFTWHITE, PACKET_MONITOR, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_RAW_CAPTURE, TFT_WHITE);
- });
-
- this->addNodes(&wifiSnifferMenu, text_table1[47], TFTRED, PWNAGOTCHI, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_PWN, TFT_RED);
- });
-
- this->addNodes(&wifiSnifferMenu, text_table1[63], TFTYELLOW, PINESCAN_SNIFF, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_PINESCAN, TFT_YELLOW);
- });
-
- this->addNodes(&wifiSnifferMenu, text_table1[64], TFTORANGE, MULTISSID_SNIFF, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_MULTISSID, TFT_ORANGE);
- });
- this->addNodes(&wifiSnifferMenu, "Scan AP/STA", TFTLIME, BEACON_SNIFF, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_AP_STA, 0x97e0);
- });
- /*this->addNodes(&wifiSnifferMenu, "Fox Hunt", TFTCYAN, PACKET_MONITOR, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_SIG_STREN, TFT_CYAN);
- });*/
+ selectProbeSSIDsMenu.list = new LinkedList();
+
+ // WiFi HTML menu stuff
+ htmlMenu.list = new LinkedList();
+ miniKbMenu.list = new LinkedList();
+ #ifdef HAS_SD
+ sdDeleteMenu.list = new LinkedList();
+ #endif
+
+ // Bluetooth menu stuff
+ bluetoothSnifferMenu.list = new LinkedList();
+ bluetoothAttackMenu.list = new LinkedList();
+
+ // Settings stuff
+ generateSSIDsMenu.list = new LinkedList();
+ clearSSIDsMenu.list = new LinkedList();
+ clearAPsMenu.list = new LinkedList();
+ saveFileMenu.list = new LinkedList();
+
+ #ifdef HAS_DIRECT_UPLOAD
+ uploadLogsMenu.list = new LinkedList();
+ uploadAllMenu.list = new LinkedList();
+ deleteAllMenu.list = new LinkedList();
+ actionMenu.list = new LinkedList();
+ #endif
+
+ saveSSIDsMenu.list = new LinkedList();
+ loadSSIDsMenu.list = new LinkedList();
+ saveAPsMenu.list = new LinkedList();
+ loadAPsMenu.list = new LinkedList();
+ saveATsMenu.list = new LinkedList();
+ loadATsMenu.list = new LinkedList();
+
+ evilPortalMenu.list = new LinkedList();
+ ssidsMenu.list = new LinkedList();
+
+ #ifdef HAS_GPS
+ gpsPOIMenu.list = new LinkedList();
+ #endif
+
+ foxHuntMenu.list = new LinkedList();
+
+ // Work menu names
+ mainMenu.name = text_table1[6];
+ wifiMenu.name = text_table1[7];
+ deviceMenu.name = text_table1[9];
+ failedUpdateMenu.name = text_table1[11];
+ confirmMenu.name = text_table1[13];
+ updateMenu.name = text_table1[15];
+ infoMenu.name = text_table1[17];
+ settingsMenu.name = text_table1[18];
+ bluetoothMenu.name = text_table1[19];
+ wifiSnifferMenu.name = text_table1[20];
+ wifiScannerMenu.name = "Scanners";
+ wifiAttackMenu.name = text_table1[21];
+ wifiGeneralMenu.name = text_table1[22];
+ saveFileMenu.name = "Save/Load Files";
+ saveSSIDsMenu.name = "Save SSIDs";
+ loadSSIDsMenu.name = "Load SSIDs";
+ saveAPsMenu.name = "Save APs";
+ loadAPsMenu.name = "Load APs";
+ saveATsMenu.name = "Save Airtags";
+ loadATsMenu.name = "Load Airtags";
+
+ bluetoothSnifferMenu.name = text_table1[23];
+ bluetoothAttackMenu.name = "Bluetooth Attacks";
+ generateSSIDsMenu.name = text_table1[27];
+ clearSSIDsMenu.name = text_table1[28];
+ clearAPsMenu.name = text_table1[29];
+ wifiAPMenu.name = "Select";
+ wifiIPMenu.name = "Active IPs";
+ apInfoMenu.name = "AP Info";
+ setMacMenu.name = "Set MACs";
+ genAPMacMenu.name = "Generate AP MAC";
+ wifiStationMenu.name = "Select Stations";
+
+ #ifdef HAS_DIRECT_UPLOAD
+ uploadLogsMenu.name = "Upload Logs";
+ uploadAllMenu.name = "Upload All?";
+ deleteAllMenu.name = "Delete All?";
+ actionMenu.name = "Destination";
+ #endif
+
+ #ifdef HAS_GPS
+ gpsMenu.name = "GPS";
+ gpsInfoMenu.name = "GPS Data";
+ //wardrivingMenu.name = "Wardriving";
+ #endif
+ htmlMenu.name = "EP HTML List";
+ miniKbMenu.name = "Mini Keyboard";
+
+ #ifdef HAS_SD
+ sdDeleteMenu.name = "Delete SD Files";
+ #endif
+
+ selectProbeSSIDsMenu.name = "Probe Requests";
+ evilPortalMenu.name = "Evil Portal";
+ ssidsMenu.name = "SSIDs";
+
+ #ifdef HAS_GPS
+ gpsPOIMenu.name = "GPS POI";
+ #endif
+
+ foxHuntMenu.name = "Fox Hunt";
+
+ // Build Main Menu
+ mainMenu.parentMenu = NULL;
+ this->addNodes(&mainMenu, text_table1[7], TFTGREEN, WIFI, [this]() {
+ this->changeMenu(&wifiMenu, true);
+ });
+ #ifdef HAS_BT
+ this->addNodes(&mainMenu, text_table1[19], TFTCYAN, BLUETOOTH, [this]() {
+ this->changeMenu(&bluetoothMenu, true);
+ });
+ #endif
+ #ifdef HAS_GPS
+ if (gps_obj.getGpsModuleStatus()) {
+ this->addNodes(&mainMenu, text1_66, TFTRED, GPS_MENU, [this]() {
+ this->changeMenu(&gpsMenu, true);
+ });
+ }
+ #endif
+ this->addNodes(&mainMenu, text_table1[9], TFTBLUE, DEVICE, [this]() {
+ this->changeMenu(&deviceMenu, true);
+ });
+ this->addNodes(&mainMenu, text_table1[30], TFTLIGHTGREY, REBOOT, []() {
+ ESP.restart();
+ });
+
+ // Build WiFi Menu
+ wifiMenu.parentMenu = &mainMenu; // Main Menu is second menu parent
+ this->addNodes(&wifiMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(wifiMenu.parentMenu, true);
+ });
+ this->addNodes(&wifiMenu, text_table1[31], TFTYELLOW, SNIFFERS, [this]() {
+ this->changeMenu(&wifiSnifferMenu, true);
+ });
+ this->addNodes(&wifiMenu, "Scanners", TFTORANGE, SCANNERS, [this]() {
+ this->changeMenu(&wifiScannerMenu, true);
+ });
+ /*#ifdef HAS_GPS
+ this->addNodes(&wifiMenu, "Wardriving", TFTGREEN, NULL, BEACON_SNIFF, [this]() {
+ this->changeMenu(&wardrivingMenu, true);
+ });
+ #endif*/
+ this->addNodes(&wifiMenu, text_table1[32], TFTRED, ATTACKS, [this]() {
+ this->changeMenu(&wifiAttackMenu, true);
+ });
+ this->addNodes(&wifiMenu, text_table1[33], TFTPURPLE, GENERAL_APPS, [this]() {
+ this->changeMenu(&wifiGeneralMenu, true);
+ });
+
+ // Build WiFi scanner Menu
+ wifiScannerMenu.parentMenu = &wifiMenu; // Main Menu is second menu parent
+ this->addNodes(&wifiScannerMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(wifiScannerMenu.parentMenu, true);
+ });
+ this->addNodes(&wifiScannerMenu, "Ping Scan", TFTGREEN, SCANNERS, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_PING_SCAN, TFT_CYAN);
+ });
+ #ifndef HAS_DUAL_BAND
+ this->addNodes(&wifiScannerMenu, "ARP Scan", TFTCYAN, SCANNERS, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_ARP_SCAN, TFT_CYAN);
+ });
+ #endif
+ this->addNodes(&wifiScannerMenu, "Port Scan All", TFTMAGENTA, BEACON_LIST, [this](){
+ // Add the back button
+ wifiIPMenu.list->clear();
+ this->addNodes(&wifiIPMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(wifiIPMenu.parentMenu, true);
+ });
+
+ // Populate the menu with buttons
+ for (int i = 0; i < ipList->size(); i++) {
+ // This is the menu node
+ this->addNodes(&wifiIPMenu, ipList->get(i).toString().c_str(), TFTBLUE, 255, [this, i](){
+ Serial.println("Selected: " + ipList->get(i).toString());
+ wifi_scan_obj.current_scan_ip = ipList->get(i);
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_PORT_SCAN_ALL, TFT_BLUE);
+ });
+ }
+ this->changeMenu(&wifiIPMenu, true);
+ });
+ this->addNodes(&wifiScannerMenu, "SSH Scan", TFTORANGE, SCANNERS, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_SSH, TFT_CYAN);
+ });
+ this->addNodes(&wifiScannerMenu, "Telnet Scan", TFTRED, SCANNERS, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_TELNET, TFT_CYAN);
+ });
+ this->addNodes(&wifiScannerMenu, "SMTP Scan", TFTWHITE, SCANNERS, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_SMTP, TFT_CYAN);
+ });
+ this->addNodes(&wifiScannerMenu, "DNS Scan", TFTLIME, SCANNERS, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_DNS, TFT_CYAN);
+ });
+ this->addNodes(&wifiScannerMenu, "HTTP Scan", TFTSKYBLUE, SCANNERS, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_HTTP, TFT_CYAN);
+ });
+ this->addNodes(&wifiScannerMenu, "HTTPS Scan", TFTYELLOW, SCANNERS, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_HTTPS, TFT_CYAN);
+ });
+ this->addNodes(&wifiScannerMenu, "RDP Scan", TFTPURPLE, SCANNERS, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_RDP, TFT_CYAN);
+ });
+
+ // Build WiFi sniffer Menu
+ wifiSnifferMenu.parentMenu = &wifiMenu; // Main Menu is second menu parent
+ this->addNodes(&wifiSnifferMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(wifiSnifferMenu.parentMenu, true);
+ });
+ this->addNodes(&wifiSnifferMenu, text_table1[42], TFTCYAN, PROBE_SNIFF, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_PROBE, TFT_CYAN);
+ });
+ this->addNodes(&wifiSnifferMenu, text_table1[43], TFTMAGENTA, BEACON_SNIFF, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_AP, TFT_MAGENTA);
+ });
+ this->addNodes(&wifiSnifferMenu, text_table1[44], TFTRED, DEAUTH_SNIFF, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_DEAUTH, TFT_RED);
+ });
+ this->addNodes(&wifiSnifferMenu, "Packet Count", TFTORANGE, PACKET_MONITOR, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_PACKET_RATE, TFT_ORANGE);
+ wifi_scan_obj.renderPacketRate();
+ });
+ #ifdef HAS_ILI9341
+ this->addNodes(&wifiSnifferMenu, text_table1[46], TFTVIOLET, EAPOL, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_EAPOL, TFT_VIOLET);
+ });
+ this->addNodes(&wifiSnifferMenu, text_table1[45], TFTBLUE, PACKET_MONITOR, [this]() {
+ wifi_scan_obj.StartScan(WIFI_PACKET_MONITOR, TFT_BLUE);
+ });
+ #else // No touch
+ this->addNodes(&wifiSnifferMenu, text_table1[46], TFTVIOLET, EAPOL, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_EAPOL, TFT_VIOLET);
+ });
+ this->addNodes(&wifiSnifferMenu, text_table1[45], TFTBLUE, PACKET_MONITOR, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_PACKET_MONITOR, TFT_BLUE);
+ });
+ #endif
+ this->addNodes(&wifiSnifferMenu, "Channel Analyzer", TFTCYAN, PACKET_MONITOR, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ this->renderGraphUI(WIFI_SCAN_CHAN_ANALYZER);
+ wifi_scan_obj.StartScan(WIFI_SCAN_CHAN_ANALYZER, TFT_CYAN);
+ });
+ this->addNodes(&wifiSnifferMenu, "Channel Summary", TFTORANGE, PACKET_MONITOR, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ this->renderGraphUI(WIFI_SCAN_CHAN_ACT);
+ wifi_scan_obj.StartScan(WIFI_SCAN_CHAN_ACT, TFT_CYAN);
+ });
+
+ this->addNodes(&wifiSnifferMenu, text_table1[58], TFTWHITE, PACKET_MONITOR, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_RAW_CAPTURE, TFT_WHITE);
+ });
+
+ this->addNodes(&wifiSnifferMenu, text_table1[47], TFTRED, PWNAGOTCHI, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_PWN, TFT_RED);
+ });
+
+ this->addNodes(&wifiSnifferMenu, text_table1[63], TFTYELLOW, PINESCAN_SNIFF, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_PINESCAN, TFT_YELLOW);
+ });
+
+ this->addNodes(&wifiSnifferMenu, text_table1[64], TFTORANGE, MULTISSID_SNIFF, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_MULTISSID, TFT_ORANGE);
+ });
+ this->addNodes(&wifiSnifferMenu, "Scan AP/STA", TFTLIME, BEACON_SNIFF, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_AP_STA, 0x97e0);
+ });
+ /*this->addNodes(&wifiSnifferMenu, "Fox Hunt", TFTCYAN, PACKET_MONITOR, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_SIG_STREN, TFT_CYAN);
+ });*/
this->addNodes(&wifiSnifferMenu, "Fox Hunt", TFTCYAN, SCANNERS, [this]() {
this->buildWiFiFoxHuntMenu();
+ });
+ this->addNodes(&wifiSnifferMenu, "MAC Monitor", TFTMAGENTA, SCANNERS, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_DETECT_FOLLOW, TFT_MAGENTA);
+ });
+ this->addNodes(&wifiSnifferMenu, "SAE Commit", TFTLIME, EAPOL, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_SAE_COMMIT, TFT_GREEN);
+ });
+
+ // Build Wardriving menu
+ #ifdef HAS_GPS
+ /*wardrivingMenu.parentMenu = &wifiMenu; // Main Menu is second menu parent
+ this->addNodes(&wardrivingMenu, text09, TFTLIGHTGREY, NULL, 0, [this]() {
+ this->changeMenu(wardrivingMenu.parentMenu, true);
+ });*/
+ if (gps_obj.getGpsModuleStatus()) {
+ this->addNodes(&wifiSnifferMenu, "Wardrive", TFTGREEN, BEACON_SNIFF, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_WAR_DRIVE, TFT_GREEN);
+ });
+ }
+ #endif
+ /*#ifdef HAS_GPS
+ if (gps_obj.getGpsModuleStatus()) {
+ this->addNodes(&wardrivingMenu, "Station Wardrive", TFTORANGE, NULL, PROBE_SNIFF, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_STATION_WAR_DRIVE, TFT_ORANGE);
+ });
+ }
+ #endif*/
+
+ // Build WiFi attack menu
+ wifiAttackMenu.parentMenu = &wifiMenu; // Main Menu is second menu parent
+ this->addNodes(&wifiAttackMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(wifiAttackMenu.parentMenu, true);
+ });
+ this->addNodes(&wifiAttackMenu, text_table1[50], TFTRED, BEACON_LIST, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_ATTACK_BEACON_LIST, TFT_RED);
+ });
+ this->addNodes(&wifiAttackMenu, text_table1[51], TFTORANGE, BEACON_SPAM, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_ATTACK_BEACON_SPAM, TFT_ORANGE);
+ });
+ this->addNodes(&wifiAttackMenu, text1_67, TFTCYAN, FUNNY_BEACON, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_ATTACK_FUNNY_BEACON, TFT_CYAN);
+ });
+ this->addNodes(&wifiAttackMenu, text_table1[52], TFTYELLOW, RICK_ROLL, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_ATTACK_RICK_ROLL, TFT_YELLOW);
+ });
+ this->addNodes(&wifiAttackMenu, text_table1[53], TFTRED, PROBE_SNIFF, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_ATTACK_AUTH, TFT_RED);
+ });
+ this->addNodes(&wifiAttackMenu, "Evil Portal", TFTORANGE, BEACON_SNIFF, [this]() {
+
+ wifiAPMenu.list->clear();
+ ssidsMenu.list->clear();
+
+ wifiAPMenu.parentMenu = &evilPortalMenu;
+ ssidsMenu.parentMenu = &evilPortalMenu;
+
+ this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(wifiAPMenu.parentMenu, true);
+ });
+ this->addNodes(&ssidsMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(ssidsMenu.parentMenu, true);
+ });
+
+ // Get AP list ready
+ for (int i = 0; i < access_points->size(); i++) {
+ // This is the menu node
+ this->addNodes(&wifiAPMenu, access_points->get(i).essid.c_str(), TFTCYAN, 255, [this, i](){
+ if (evil_portal_obj.setAP(access_points->get(i).essid)) {
+ AccessPoint new_ap = access_points->get(i);
+ new_ap.selected = true;
+ access_points->set(i, new_ap);
+
+ evil_portal_obj.ap_index = i;
+
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_EVIL_PORTAL, TFT_ORANGE);
+ wifi_scan_obj.setMac();
+ }
+ else
+ this->changeMenu(&evilPortalMenu, true);
+ });
+ }
+
+ for (int i = 0; i < ssids->size(); i++) {
+ // This is the menu node
+ this->addNodes(&ssidsMenu, ssids->get(i).essid.c_str(), TFTCYAN, 255, [this, i](){
+ if (evil_portal_obj.setAP(ssids->get(i).essid)) {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_EVIL_PORTAL, TFT_ORANGE);
+ wifi_scan_obj.setMac();
+ }
+ else
+ this->changeMenu(&evilPortalMenu, true);
+ });
+ }
+ this->changeMenu(&evilPortalMenu, true);
+ });
+ this->addNodes(&wifiAttackMenu, text_table1[54], TFTRED, DEAUTH_SNIFF, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_ATTACK_DEAUTH, TFT_RED);
+ });
+ this->addNodes(&wifiAttackMenu, text_table1[57], TFTMAGENTA, BEACON_LIST, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_ATTACK_AP_SPAM, TFT_MAGENTA);
+ });
+ this->addNodes(&wifiAttackMenu, text_table1[62], TFTRED, DEAUTH_SNIFF, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_ATTACK_DEAUTH_TARGETED, TFT_ORANGE);
+ });
+
+ this->addNodes(&wifiAttackMenu, "Karma", TFTORANGE, KEYBOARD_ICO, [this](){
+ // Add the back button
+ selectProbeSSIDsMenu.list->clear();
+ this->addNodes(&selectProbeSSIDsMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(&wifiAttackMenu, true);
+ });
+
+ // Populate the menu with buttons
+ for (int i = 0; i < probe_req_ssids->size(); i++) {
+ // This is the menu node
+ this->addNodes(&selectProbeSSIDsMenu, probe_req_ssids->get(i).essid.c_str(), TFTCYAN, 255, [this, i](){
+ if (evil_portal_obj.setAP(probe_req_ssids->get(i).essid)) {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_EVIL_PORTAL, TFT_ORANGE);
+ wifi_scan_obj.setMac();
+ }
+ else
+ this->changeMenu(&wifiAttackMenu, true);
+ });
+ }
+ this->changeMenu(&selectProbeSSIDsMenu, true);
+ });
+
+ this->addNodes(&wifiAttackMenu, "Bad Msg", TFTRED, DEAUTH_SNIFF, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_ATTACK_BAD_MSG, TFT_RED);
+ });
+ this->addNodes(&wifiAttackMenu, "Bad Msg Targeted", TFTYELLOW, DEAUTH_SNIFF, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_ATTACK_BAD_MSG_TARGETED, TFT_YELLOW);
+ });
+ this->addNodes(&wifiAttackMenu, "Assoc Sleep", TFTRED, DEAUTH_SNIFF, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_ATTACK_SLEEP, TFT_RED);
+ });
+ this->addNodes(&wifiAttackMenu, "Assoc Sleep Targ", TFTMAGENTA, DEAUTH_SNIFF, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_ATTACK_SLEEP_TARGETED, TFT_MAGENTA);
+ });
+ this->addNodes(&wifiAttackMenu, "SAE Commit Flood", TFTLIME, EAPOL, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_ATTACK_SAE_COMMIT, TFT_GREEN);
+ });
+ this->addNodes(&wifiAttackMenu, "Channel Switch", TFTORANGE, BEACON_LIST, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_ATTACK_CSA, TFT_GREEN);
+ });
+ this->addNodes(&wifiAttackMenu, "Quiet Time", TFTRED, BEACON_LIST, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_ATTACK_QUIET, TFT_GREEN);
+ });
+
+ evilPortalMenu.parentMenu = &wifiAttackMenu;
+ this->addNodes(&evilPortalMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(evilPortalMenu.parentMenu, true);
+ });
+ this->addNodes(&evilPortalMenu, "Access Points", TFTGREEN, BEACON_SNIFF, [this]() {
+ this->changeMenu(&wifiAPMenu, true);
+ });
+ this->addNodes(&evilPortalMenu, "User SSIDs", TFTCYAN, PROBE_SNIFF, [this]() {
+ this->changeMenu(&ssidsMenu, true);
+ });
+
+ // Build WiFi General menu
+ wifiGeneralMenu.parentMenu = &wifiMenu;
+ this->addNodes(&wifiGeneralMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(wifiGeneralMenu.parentMenu, true);
+ });
+ this->addNodes(&wifiGeneralMenu, text_table1[27], TFTSKYBLUE, GENERATE, [this]() {
+ this->changeMenu(&generateSSIDsMenu, true);
+ wifi_scan_obj.RunGenerateSSIDs();
+ });
+
+ //Add Select probe ssid
+ this->addNodes(&wifiGeneralMenu, text_table1[65], TFTCYAN, KEYBOARD_ICO, [this]() {
+ selectProbeSSIDsMenu.list->clear();
+
+ // Add the back button
+ this->addNodes(&selectProbeSSIDsMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(&wifiGeneralMenu, true);
+
+ // TODO: TBD - Should probe_req_ssids have it´s own life and override ap.config and/or ssids -list for EP?
+ // If so, then we should not add selected ssids to ssids list
+
+ // Add selected ssid names to ssids list when clicking back button
+ if (probe_req_ssids->size() > 0) {
+
+ //TODO: TBD - Clear ssids list before adding new ones??
+
+ for (int i = 0; i < probe_req_ssids->size(); i++) {
+ ProbeReqSsid cur_probe_ssid = probe_req_ssids->get(i);
+ if (cur_probe_ssid.selected) {
+ bool ssidExists = false;
+ for (int i = 0; i < ssids->size(); i++) {
+ if (ssids->get(i).essid == cur_probe_ssid.essid) {
+ ssidExists = true;
+ break;
+ }
+ }
+ if (!ssidExists) {
+ wifi_scan_obj.addSSID(cur_probe_ssid.essid);
+ }
+ }
+ }
+ }
+ });
+
+ // Populate the menu with buttons
+ for (int i = 0; i < probe_req_ssids->size(); i++) {
+ ProbeReqSsid cur_ssid = probe_req_ssids->get(i);
+ // This is the menu node
+ String button_name = "[" + String(cur_ssid.requests) + "]" + cur_ssid.essid;
+ this->addNodes(
+ &selectProbeSSIDsMenu,
+ button_name.c_str(),
+ TFTCYAN,
+ 255,
+ [this, i]() {
+ ProbeReqSsid new_ssid = probe_req_ssids->get(i);
+ new_ssid.selected = !probe_req_ssids->get(i).selected;
+
+ // Change selection status of menu node
+ MenuNode new_node = current_menu->list->get(i + 1);
+ new_node.selected = !current_menu->list->get(i + 1).selected;
+ current_menu->list->set(i + 1, new_node);
+
+ probe_req_ssids->set(i, new_ssid);
+ },
+ probe_req_ssids->get(i).selected);
+ }
+ this->changeMenu(&selectProbeSSIDsMenu, true);
+ });
+
+ clearSSIDsMenu.parentMenu = &wifiGeneralMenu;
+
+ #ifdef HAS_ILI9341
+ this->addNodes(&wifiGeneralMenu, text_table1[1], TFTNAVY, KEYBOARD_ICO, [this](){
+ char ssidBuf[64] = {0};
+ bool keep_going = true;
+ while (keep_going) {
+ display_obj.clearScreen();
+ if (keyboardInput(ssidBuf, sizeof(ssidBuf), "Enter SSID")) {
+ if (ssidBuf[0] != 0)
+ wifi_scan_obj.addSSID(String(ssidBuf));
+ for (int i = 0; i < 64; i++)
+ ssidBuf[i] = NULL;
+ }
+ else
+ keep_going = false;
+ }
+
+ this->changeMenu(current_menu);
+ });
+ #endif
+ #if (!defined(HAS_ILI9341) && defined(HAS_BUTTONS))
+ this->addNodes(&wifiGeneralMenu, text_table1[1], TFTNAVY, KEYBOARD_ICO, [this](){
+ this->changeMenu(&miniKbMenu, true);
+ #ifdef HAS_MINI_KB
+ this->miniKeyboard(&miniKbMenu);
+ #endif
+ });
+ #endif
+ this->addNodes(&wifiGeneralMenu, text_table1[28], TFTSILVER, CLEAR_ICO, [this]() {
+ this->changeMenu(&clearSSIDsMenu, true);
+ wifi_scan_obj.RunClearSSIDs();
+ });
+ this->addNodes(&wifiGeneralMenu, text_table1[29], TFTDARKGREY, CLEAR_ICO, [this]() {
+ this->changeMenu(&clearAPsMenu, true);
+ wifi_scan_obj.RunClearAPs();
+ });
+ this->addNodes(&wifiGeneralMenu, text_table1[60], TFTBLUE, CLEAR_ICO, [this]() {
+ this->changeMenu(&clearAPsMenu, true);
+ wifi_scan_obj.RunClearStations();
+ });
+ //#else // Mini EP HTML select
+ this->addNodes(&wifiGeneralMenu, "Select EP HTML File", TFTCYAN, KEYBOARD_ICO, [this](){
+ // Add the back button
+ htmlMenu.list->clear();
+ this->addNodes(&htmlMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(htmlMenu.parentMenu, true);
+ });
+
+ // Populate the menu with buttons
+ for (int i = 0; i < evil_portal_obj.html_files->size(); i++) {
+ // This is the menu node
+ this->addNodes(&htmlMenu, evil_portal_obj.html_files->get(i).c_str(), TFTCYAN, 255, [this, i](){
+ evil_portal_obj.selected_html_index = i;
+ evil_portal_obj.target_html_name = evil_portal_obj.html_files->get(evil_portal_obj.selected_html_index);
+ Serial.println("Set Evil Portal HTML as " + evil_portal_obj.target_html_name);
+ evil_portal_obj.using_serial_html = false;
+ this->changeMenu(htmlMenu.parentMenu, true);
+ return;
+ });
+ }
+ this->changeMenu(&htmlMenu, true);
+ });
+
+ //#if (!defined(HAS_ILI9341) && defined(HAS_BUTTONS))
+ miniKbMenu.parentMenu = &wifiGeneralMenu;
+ #if !defined(MARAUDER_CARDPUTER) && !defined(MARAUDER_CARDPUTER_ADV)
+ this->addNodes(&miniKbMenu, "a", TFTCYAN, 0, [this]() {
+ this->changeMenu(miniKbMenu.parentMenu, true);
+ });
+ #endif
+ //#endif
+
+ htmlMenu.parentMenu = &wifiGeneralMenu;
+ this->addNodes(&htmlMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(htmlMenu.parentMenu, true);
+ });
+
+ // Select APs on Mini
+ this->addNodes(&wifiGeneralMenu, "Select APs", TFTNAVY, KEYBOARD_ICO, [this](){
+ wifiAPMenu.parentMenu = &wifiGeneralMenu;
+ // Add the back button
+ wifiAPMenu.list->clear();
+ this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(wifiAPMenu.parentMenu, true);
+ });
+
+ this->addNodes(&wifiAPMenu, "Select ALL", TFTGREEN, 255, [this](){
+
+ for (int x = 0; x < access_points->size(); x++) {
+ AccessPoint new_ap = access_points->get(x);
+ new_ap.selected = !access_points->get(x).selected;
+ access_points->set(x, new_ap);
+
+ MenuNode new_node = current_menu->list->get(x + 2);
+ new_node.selected = !current_menu->list->get(x + 2).selected;
+ current_menu->list->set(x + 2, new_node);
+ }
+
+ this->changeMenu(current_menu, true);
+
+ });
+
+ // Populate the menu with buttons
+ for (int i = 0; i < access_points->size(); i++) {
+ // This is the menu node
+ this->addNodes(&wifiAPMenu, access_points->get(i).essid.c_str(), TFTCYAN, 255, [this, i](){
+ AccessPoint new_ap = access_points->get(i);
+ new_ap.selected = !access_points->get(i).selected;
+
+ // Change selection status of menu node
+ MenuNode new_node = current_menu->list->get(i + 2);
+ new_node.selected = !current_menu->list->get(i + 2).selected;
+ current_menu->list->set(i + 2, new_node);
+
+ access_points->set(i, new_ap);
+ }, access_points->get(i).selected);
+ }
+ this->changeMenu(&wifiAPMenu, true);
+ });
+
+ this->addNodes(&wifiGeneralMenu, "View AP Info", TFTCYAN, KEYBOARD_ICO, [this](){
+ wifiAPMenu.parentMenu = &wifiGeneralMenu;
+
+ // Add the back button
+ wifiAPMenu.list->clear();
+ this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(wifiAPMenu.parentMenu, true);
+ });
+
+ // Populate the menu with buttons
+ for (int i = 0; i < access_points->size(); i++) {
+ // This is the menu node
+ this->addNodes(&wifiAPMenu, access_points->get(i).essid.c_str(), TFTCYAN, 255, [this, i](){
+ this->changeMenu(&apInfoMenu, true);
+ wifi_scan_obj.RunAPInfo(i);
+ });
+ }
+ this->changeMenu(&wifiAPMenu, true);
+ });
+
+ apInfoMenu.parentMenu = &wifiAPMenu;
+ this->addNodes(&apInfoMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(apInfoMenu.parentMenu, true);
+ });
+
+ wifiAPMenu.parentMenu = &wifiGeneralMenu;
+ this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(wifiAPMenu.parentMenu, true);
+ });
+
+ wifiIPMenu.parentMenu = &wifiScannerMenu;
+ this->addNodes(&wifiIPMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(wifiIPMenu.parentMenu, true);
+ });
+
+
+ // Select Stations on Mini v2
+ this->addNodes(&wifiGeneralMenu, "Select Stations", TFTCYAN, KEYBOARD_ICO, [this](){
+ wifiAPMenu.parentMenu = &wifiGeneralMenu;
+
+ wifiAPMenu.list->clear();
+ this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(wifiAPMenu.parentMenu, true);
+ });
+
+ int menu_limit = access_points->size();
+
+
+ for (int i = 0; i < menu_limit; i++) {
+ wifiStationMenu.list->clear();
+ this->addNodes(&wifiAPMenu, access_points->get(i).essid.c_str(), TFTCYAN, 255, [this, i](){
+
+ wifiStationMenu.list->clear();
+
+ wifiStationMenu.parentMenu = &wifiAPMenu;
+
+ // Add back button to the APs
+ this->addNodes(&wifiStationMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(wifiStationMenu.parentMenu, true);
+ });
+
+ this->addNodes(&wifiStationMenu, "Select ALL", TFTGREEN, 255, [this, i](){
+
+ for (int y = 0; y < access_points->get(i).stations->size(); y++) {
+ int cur_ap_sta_inx = access_points->get(i).stations->get(y);
+ Station new_sta = stations->get(cur_ap_sta_inx);
+ new_sta.selected = !stations->get(cur_ap_sta_inx).selected;
+
+ // Change selection status of menu node
+ MenuNode new_node = current_menu->list->get(y + 2);
+ new_node.selected = !current_menu->list->get(y + 2).selected;
+ current_menu->list->set(y + 2, new_node);
+
+ stations->set(cur_ap_sta_inx, new_sta);
+ }
+
+ this->changeMenu(current_menu, true);
+
+ });
+
+ // Add the AP's stations to the specific AP menu
+ for (int x = 0; x < access_points->get(i).stations->size(); x++) {
+ int cur_ap_sta = access_points->get(i).stations->get(x);
+
+ this->addNodes(&wifiStationMenu, macToString(stations->get(cur_ap_sta)).c_str(), TFTCYAN, 255, [this, i, cur_ap_sta, x](){
+ Station new_sta = stations->get(cur_ap_sta);
+ new_sta.selected = !stations->get(cur_ap_sta).selected;
+
+ // Change selection status of menu node
+ MenuNode new_node = current_menu->list->get(x + 2);
+ new_node.selected = !current_menu->list->get(x + 2).selected;
+ current_menu->list->set(x + 2, new_node);
+
+ stations->set(cur_ap_sta, new_sta);
+ }, stations->get(cur_ap_sta).selected);
+ }
+
+ // Final change menu to the menu of Stations
+ this->changeMenu(&wifiStationMenu, true);
+
+ }, false);
+ }
+ this->changeMenu(&wifiAPMenu, true);
+ });
+
+ this->addNodes(&wifiGeneralMenu, "Join WiFi", TFTWHITE, KEYBOARD_ICO, [this](){
+
+ wifiAPMenu.parentMenu = &wifiGeneralMenu;
+
+ // Add the back button
+ wifiAPMenu.list->clear();
+ this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(wifiAPMenu.parentMenu, true);
+ });
+
+ // Populate the menu with buttons
+ for (int i = 0; i < access_points->size(); i++) {
+ // This is the menu node
+ this->addNodes(&wifiAPMenu, access_points->get(i).essid.c_str(), TFTCYAN, 255, [this, i](){
+ // Join WiFi using mini keyboard
+ #ifdef HAS_MINI_KB
+ this->changeMenu(&miniKbMenu, true);
+ String password = this->miniKeyboard(&miniKbMenu, true);
+ if (password != "") {
+ Serial.println("Using SSID: " + (String)access_points->get(i).essid + " Password: " + (String)password);
+ wifi_scan_obj.currentScanMode = LV_JOIN_WIFI;
+ wifi_scan_obj.StartScan(LV_JOIN_WIFI, TFT_YELLOW);
+ wifi_scan_obj.joinWiFi(access_points->get(i).essid, password);
+ this->changeMenu(current_menu, true);
+ }
+ #endif
+
+ // Join WiFi using touch screen keyboard
+ #ifdef HAS_TOUCH
+ char passwordBuf[64] = {0}; // or prefill with existing SSID
+ if (keyboardInput(passwordBuf, sizeof(passwordBuf), "Enter Password")) {
+ wifi_scan_obj.joinWiFi(access_points->get(i).essid, String(passwordBuf), true);
+ }
+
+ this->changeMenu(&wifiGeneralMenu, true);
+ #endif
+ });
+ }
+ this->changeMenu(&wifiAPMenu, true);
+ });
+
+ this->addNodes(&wifiGeneralMenu, "Join Saved WiFi", TFTWHITE, KEYBOARD_ICO, [this](){
+ String ssid = settings_obj.loadSetting("ClientSSID");
+ String pw = settings_obj.loadSetting("ClientPW");
+
+ if ((ssid != "") && (pw != "")) {
+ wifi_scan_obj.joinWiFi(ssid, pw, false);
+ this->changeMenu(&wifiGeneralMenu, true);
+ }
+ else {
+ wifiAPMenu.parentMenu = &wifiGeneralMenu;
+
+ // Add the back button
+ wifiAPMenu.list->clear();
+ this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(wifiAPMenu.parentMenu, true);
+ });
+
+ // Populate the menu with buttons
+ for (int i = 0; i < access_points->size(); i++) {
+ // This is the menu node
+ this->addNodes(&wifiAPMenu, access_points->get(i).essid.c_str(), TFTCYAN, 255, [this, i](){
+ // Join WiFi using mini keyboard
+ #ifdef HAS_MINI_KB
+ this->changeMenu(&miniKbMenu, true);
+ String password = this->miniKeyboard(&miniKbMenu, true);
+ if (password != "") {
+ Serial.println("Using SSID: " + (String)access_points->get(i).essid + " Password: " + (String)password);
+ wifi_scan_obj.currentScanMode = LV_JOIN_WIFI;
+ wifi_scan_obj.StartScan(LV_JOIN_WIFI, TFT_YELLOW);
+ wifi_scan_obj.joinWiFi(access_points->get(i).essid, password);
+ this->changeMenu(current_menu, true);
+ }
+ #endif
+
+ // Join WiFi using touch screen keyboard
+ #ifdef HAS_TOUCH
+ char passwordBuf[64] = {0}; // or prefill with existing SSID
+ if (keyboardInput(passwordBuf, sizeof(passwordBuf), "Enter Password")) {
+ wifi_scan_obj.joinWiFi(access_points->get(i).essid, String(passwordBuf), true);
+ }
+
+ this->changeMenu(&wifiGeneralMenu, true);
+ #endif
+ });
+ }
+ this->changeMenu(&wifiAPMenu, true);
+ }
+ });
+
+ this->addNodes(&wifiGeneralMenu, "Start AP", TFTGREEN, KEYBOARD_ICO, [this](){
+ ssidsMenu.parentMenu = &wifiGeneralMenu;
+
+ // Add the back button
+ ssidsMenu.list->clear();
+ this->addNodes(&ssidsMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(ssidsMenu.parentMenu, true);
+ });
+
+ // Populate the menu with buttons
+ for (int i = 0; i < ssids->size(); i++) {
+ // This is the menu node
+ this->addNodes(&ssidsMenu, ssids->get(i).essid.c_str(), TFTCYAN, 255, [this, i](){
+ // Join WiFi using mini keyboard
+ #ifdef HAS_MINI_KB
+ this->changeMenu(&miniKbMenu, true);
+ String password = this->miniKeyboard(&miniKbMenu, true);
+ if (password != "") {
+ Serial.println("Using SSID: " + (String)ssids->get(i).essid + " Password: " + (String)password);
+ wifi_scan_obj.currentScanMode = LV_JOIN_WIFI;
+ wifi_scan_obj.StartScan(LV_JOIN_WIFI, TFT_YELLOW);
+ wifi_scan_obj.startWiFi(ssids->get(i).essid, password);
+ this->changeMenu(current_menu, true);
+ }
+ #endif
+
+ // Join WiFi using touch screen keyboard
+ #ifdef HAS_TOUCH
+ char passwordBuf[64] = {0}; // or prefill with existing SSID
+ if (keyboardInput(passwordBuf, sizeof(passwordBuf), "Enter Password")) {
+ Serial.println("Using SSID: " + (String)ssids->get(i).essid + " Password: " + String(passwordBuf));
+ wifi_scan_obj.startWiFi(ssids->get(i).essid, String(passwordBuf));
+ }
+
+ this->changeMenu(&wifiGeneralMenu, false);
+ #endif
+ });
+ }
+ this->changeMenu(&ssidsMenu, true);
+ });
+
+ this->addNodes(&wifiGeneralMenu, "Host AP Info", TFTGREEN, BEACON_SNIFF, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(WIFI_SCAN_DISPLAY_AP_INFO, TFT_GREEN);
+ });
+
+ wifiStationMenu.parentMenu = &ssidsMenu;
+ this->addNodes(&wifiStationMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(wifiStationMenu.parentMenu, true);
+ });
+
+ this->addNodes(&wifiGeneralMenu, "Set MACs", TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(&setMacMenu, true);
+ });
+
+ this->addNodes(&wifiGeneralMenu, "Shutdown WiFi", TFTRED, 0, [this]() {
+ WiFi.softAPdisconnect(true); // Also shut down the SoftAP if it is running
+ WiFi.disconnect(true);
+ delay(100);
+ wifi_scan_obj.StartScan(WIFI_SCAN_OFF, TFT_RED);
+ this->changeMenu(current_menu, true);
+ });
+
+ #ifdef HAS_DIRECT_UPLOAD
+ this->addNodes(&wifiGeneralMenu, "Upload Wardrive Logs", TFTGREEN, 0, [this]() {
+ display_obj.clearScreen();
+ display_obj.tft.setTextWrap(false);
+ display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
+ display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
+ display_obj.tft.println("Loading...");
+
+ this->buildUploadFileMenu();
+
+ this->changeMenu(&uploadLogsMenu, true);
+ });
+
+ uploadAllMenu.parentMenu = &uploadLogsMenu;
+ this->addNodes(&uploadAllMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(uploadAllMenu.parentMenu, true);
+ });
+ this->addNodes(&uploadAllMenu, "WiGLE", TFTLIGHTGREY, 0, [this]() {
+ display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
+
+ String ssid = settings_obj.loadSetting("ClientSSID");
+ String pw = settings_obj.loadSetting("ClientPW");
+
+ if ((ssid == "") && (pw == "")) {
+ display_obj.clearScreen();
+ display_obj.tft.setTextWrap(true);
+ display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
+ display_obj.tft.println("WiFi Credentials Empty.");
+ display_obj.tft.println("Returning...");
+ display_obj.tft.setTextWrap(false);
+ }
+ else {
+ display_obj.clearScreen();
+ display_obj.showCenterText(String("Connecting to " + ssid).c_str(), TFT_HEIGHT / 2, true);
+ if (!wifi_scan_obj.joinWiFi(ssid, pw, false)) {
+ display_obj.clearScreen();
+ display_obj.tft.setTextWrap(true);
+ display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
+ display_obj.tft.println("Could not connect to WiFi.");
+ display_obj.tft.println("Returning...");
+ display_obj.tft.setTextWrap(false);
+ }
+ else {
+ delay(1000);
+ for (int i = 0; i < sd_obj.sd_files->size(); i++) {
+ if (sd_obj.sd_files->get(i).startsWith("wardrive_") || sd_obj.sd_files->get(i).startsWith("wigle-")) {
+ if (!sd_obj.sd_files->get(i).endsWith(".wigle") && !sd_obj.sd_files->get(i).endsWith(".wdg") && !sd_obj.sd_files->get(i).endsWith(".gpx")) {
+ Serial.println("Uploading " + sd_obj.sd_files->get(i) + "...");
+ if (wifi_scan_obj.uploadFile("/" + sd_obj.sd_files->get(i), true, WIGLE_UPLOAD)) {
+ display_obj.clearScreen();
+ display_obj.showCenterText("WiGLE OK", TFT_HEIGHT / 2);
+ } else {
+ display_obj.clearScreen();
+ display_obj.showCenterText("WiGLE failed", TFT_HEIGHT / 2);
+ }
+ }
+ }
+ }
+ WiFi.disconnect(true);
+ delay(100);
+ wifi_scan_obj.StartScan(WIFI_SCAN_OFF, TFT_RED);
+ }
+ }
+
+ delay(2000);
+
+ this->changeMenu(uploadAllMenu.parentMenu, true);
+ });
+ this->addNodes(&uploadAllMenu, "WDGWars", TFTLIGHTGREY, 0, [this]() {
+ String ssid = settings_obj.loadSetting("ClientSSID");
+ String pw = settings_obj.loadSetting("ClientPW");
+
+ display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
+
+ if ((ssid == "") && (pw == "")) {
+ display_obj.clearScreen();
+ display_obj.tft.setTextWrap(true);
+ display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
+ display_obj.tft.println("WiFi Credentials Empty.");
+ display_obj.tft.println("Returning...");
+ display_obj.tft.setTextWrap(false);
+ }
+ else {
+ display_obj.clearScreen();
+ display_obj.showCenterText(String("Connecting to " + ssid).c_str(), TFT_HEIGHT / 2, true);
+ if (!wifi_scan_obj.joinWiFi(ssid, pw, false)) {
+ display_obj.clearScreen();
+ display_obj.tft.setTextWrap(true);
+ display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
+ display_obj.tft.println("Could not connect to WiFi.");
+ display_obj.tft.println("Returning...");
+ display_obj.tft.setTextWrap(false);
+ }
+ else {
+ delay(1000);
+ for (int i = 0; i < sd_obj.sd_files->size(); i++) {
+ if (sd_obj.sd_files->get(i).startsWith("wardrive_") || sd_obj.sd_files->get(i).startsWith("wigle-")) {
+ if (!sd_obj.sd_files->get(i).endsWith(".wigle") && !sd_obj.sd_files->get(i).endsWith(".wdg") && !sd_obj.sd_files->get(i).endsWith(".gpx")) {
+ Serial.println("Uploading " + sd_obj.sd_files->get(i) + "...");
+ if (wifi_scan_obj.uploadFile("/" + sd_obj.sd_files->get(i), true, WDG_UPLOAD)) {
+ display_obj.clearScreen();
+ display_obj.showCenterText("WDG OK", TFT_HEIGHT / 2);
+ } else {
+ display_obj.clearScreen();
+ display_obj.showCenterText("WDG failed", TFT_HEIGHT / 2);
+ }
+ }
+ }
+ }
+ WiFi.disconnect(true);
+ delay(100);
+ wifi_scan_obj.StartScan(WIFI_SCAN_OFF, TFT_RED);
+ }
+ }
+
+ delay(2000);
+
+ this->changeMenu(uploadAllMenu.parentMenu, true);
+ });
+ this->addNodes(&uploadAllMenu, "Both", TFTLIGHTGREY, 0, [this]() {
+ String ssid = settings_obj.loadSetting("ClientSSID");
+ String pw = settings_obj.loadSetting("ClientPW");
+
+ display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
+
+ if ((ssid == "") && (pw == "")) {
+ display_obj.clearScreen();
+ display_obj.tft.setTextWrap(true);
+ display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
+ display_obj.tft.println("WiFi Credentials Empty.");
+ display_obj.tft.println("Returning...");
+ display_obj.tft.setTextWrap(false);
+ }
+ else {
+ display_obj.clearScreen();
+ display_obj.showCenterText(String("Connecting to " + ssid).c_str(), TFT_HEIGHT / 2, true);
+ if (!wifi_scan_obj.joinWiFi(ssid, pw, false)) {
+ display_obj.clearScreen();
+ display_obj.tft.setTextWrap(true);
+ display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
+ display_obj.tft.println("Could not connect to WiFi.");
+ display_obj.tft.println("Returning...");
+ display_obj.tft.setTextWrap(false);
+ }
+ else {
+ delay(1000);
+ for (int i = 0; i < sd_obj.sd_files->size(); i++) {
+ if (sd_obj.sd_files->get(i).startsWith("wardrive_") || sd_obj.sd_files->get(i).startsWith("wigle-")) {
+ if (!sd_obj.sd_files->get(i).endsWith(".wigle") && !sd_obj.sd_files->get(i).endsWith(".wdg") && !sd_obj.sd_files->get(i).endsWith(".gpx")) {
+ Serial.println("Uploading " + sd_obj.sd_files->get(i) + "...");
+ if (wifi_scan_obj.uploadFile("/" + sd_obj.sd_files->get(i), true, BOTH_UPLOAD)) {
+ display_obj.clearScreen();
+ display_obj.showCenterText("Upload OK", TFT_HEIGHT / 2);
+ } else {
+ display_obj.clearScreen();
+ display_obj.showCenterText("Upload failed", TFT_HEIGHT / 2);
+ }
+ }
+ }
+ }
+ WiFi.disconnect(true);
+ delay(100);
+ wifi_scan_obj.StartScan(WIFI_SCAN_OFF, TFT_RED);
+ }
+ }
+
+ delay(2000);
+
+ this->changeMenu(uploadAllMenu.parentMenu, true);
+ });
+
+ deleteAllMenu.parentMenu = &uploadLogsMenu;
+ this->addNodes(&deleteAllMenu, "No", TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(deleteAllMenu.parentMenu, true);
+ });
+ this->addNodes(&deleteAllMenu, "Yes", TFTRED, 0, [this]() {
+ display_obj.tft.setTextColor(TFT_ORANGE, TFT_BLACK);
+
+ display_obj.clearScreen();
+
+ display_obj.showCenterText("Deleting logs...", TFT_HEIGHT / 2, true);
+
+ for (int i = 0; i < sd_obj.sd_files->size(); i++) {
+ if (sd_obj.sd_files->get(i).startsWith("wardrive_") || sd_obj.sd_files->get(i).startsWith("wigle-")) {
+ if (sd_obj.removeFile("/" + sd_obj.sd_files->get(i))) {
+ Serial.println("Removed file: " + sd_obj.sd_files->get(i));
+ sd_obj.removeFile("/" + sd_obj.sd_files->get(i) + ".wdg");
+ sd_obj.removeFile("/" + sd_obj.sd_files->get(i) + ".wigle");
+ }
+ else {
+ Serial.println("Could not remove file: " + sd_obj.sd_files->get(i));
+ }
+ }
+ }
+ display_obj.clearScreen();
+
+ display_obj.showCenterText("Logs removed", TFT_HEIGHT / 2, true);
+
+ delay(2000);
+
+ this->buildUploadFileMenu();
+
+ this->changeMenu(&uploadLogsMenu, true);
+ });
+
+ actionMenu.parentMenu = &uploadLogsMenu;
+ this->addNodes(&actionMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(actionMenu.parentMenu, true);
+ });
+ this->addNodes(&actionMenu, "WiGLE", TFTLIGHTGREY, 0, [this]() {
+ String ssid = settings_obj.loadSetting("ClientSSID");
+ String pw = settings_obj.loadSetting("ClientPW");
+
+ display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
+
+ if ((ssid == "") && (pw == "")) {
+ display_obj.clearScreen();
+ display_obj.tft.setTextWrap(true);
+ display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
+ display_obj.tft.println("WiFi Credentials Empty.");
+ display_obj.tft.println("Returning...");
+ display_obj.tft.setTextWrap(false);
+ }
+ else {
+ display_obj.clearScreen();
+ display_obj.showCenterText(String("Connecting to " + ssid).c_str(), TFT_HEIGHT / 2, true);
+ if (!wifi_scan_obj.joinWiFi(ssid, pw, false)) {
+ display_obj.clearScreen();
+ display_obj.tft.setTextWrap(true);
+ display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
+ display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
+ display_obj.tft.println("Could not connect to WiFi.");
+ display_obj.tft.println("Returning...");
+ display_obj.tft.setTextWrap(false);
+ }
+ else {
+ delay(1000);
+ Serial.println("Uploading " + sd_obj.selected_file_name + "...");
+ if (wifi_scan_obj.uploadFile("/" + sd_obj.selected_file_name, true, WIGLE_UPLOAD)) {
+ display_obj.clearScreen();
+ display_obj.showCenterText("WiGLE OK", TFT_HEIGHT / 2, true);
+ } else {
+ display_obj.clearScreen();
+ display_obj.showCenterText("WiGLE failed", TFT_HEIGHT / 2, true);
+ }
+
+ WiFi.disconnect(true);
+ delay(100);
+ wifi_scan_obj.StartScan(WIFI_SCAN_OFF, TFT_RED);
+ }
+ }
+
+ delay(2000);
+
+ this->changeMenu(&actionMenu, true);
+ });
+ this->addNodes(&actionMenu, "WDGWars", TFTLIGHTGREY, 0, [this]() {
+ String ssid = settings_obj.loadSetting("ClientSSID");
+ String pw = settings_obj.loadSetting("ClientPW");
+
+ display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
+
+ if ((ssid == "") && (pw == "")) {
+ display_obj.clearScreen();
+ display_obj.tft.setTextWrap(true);
+ display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
+ display_obj.tft.println("WiFi Credentials Empty.");
+ display_obj.tft.println("Returning...");
+ display_obj.tft.setTextWrap(false);
+ }
+ else {
+ display_obj.clearScreen();
+ display_obj.showCenterText(String("Connecting to " + ssid).c_str(), TFT_HEIGHT / 2, true);
+ if (!wifi_scan_obj.joinWiFi(ssid, pw, false)) {
+ display_obj.clearScreen();
+ display_obj.tft.setTextWrap(true);
+ display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
+ display_obj.tft.println("Could not connect to WiFi.");
+ display_obj.tft.println("Returning...");
+ display_obj.tft.setTextWrap(false);
+ }
+ else {
+ delay(1000);
+ Serial.println("Uploading " + sd_obj.selected_file_name + "...");
+ if (wifi_scan_obj.uploadFile("/" + sd_obj.selected_file_name, true, WDG_UPLOAD)) {
+ display_obj.clearScreen();
+ display_obj.showCenterText("WDG OK", TFT_HEIGHT / 2, true);
+ } else {
+ display_obj.clearScreen();
+ display_obj.showCenterText("WDG failed", TFT_HEIGHT / 2, true);
+ }
+
+ WiFi.disconnect(true);
+ delay(100);
+ wifi_scan_obj.StartScan(WIFI_SCAN_OFF, TFT_RED);
+ }
+ }
+
+ delay(2000);
+
+ this->changeMenu(&actionMenu, true);
+ });
+ this->addNodes(&actionMenu, "Both", TFTLIGHTGREY, 0, [this]() {
+ String ssid = settings_obj.loadSetting("ClientSSID");
+ String pw = settings_obj.loadSetting("ClientPW");
+
+ display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
+
+ if ((ssid == "") && (pw == "")) {
+ display_obj.clearScreen();
+ display_obj.tft.setTextWrap(true);
+ display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
+ display_obj.tft.println("WiFi Credentials Empty.");
+ display_obj.tft.println("Returning...");
+ display_obj.tft.setTextWrap(false);
+ }
+ else {
+ display_obj.clearScreen();
+ display_obj.showCenterText(String("Connecting to " + ssid).c_str(), TFT_HEIGHT / 2, true);
+ if (!wifi_scan_obj.joinWiFi(ssid, pw, false)) {
+ display_obj.clearScreen();
+ display_obj.tft.setTextWrap(true);
+ display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
+ display_obj.tft.println("Could not connect to WiFi.");
+ display_obj.tft.println("Returning...");
+ display_obj.tft.setTextWrap(false);
+ }
+ else {
+ delay(1000);
+ Serial.println("Uploading " + sd_obj.selected_file_name + "...");
+ if (wifi_scan_obj.uploadFile("/" + sd_obj.selected_file_name, true, BOTH_UPLOAD)) {
+ display_obj.clearScreen();
+ display_obj.showCenterText("Upload OK", TFT_HEIGHT / 2, true);
+ } else {
+ display_obj.clearScreen();
+ display_obj.showCenterText("Upload failed", TFT_HEIGHT / 2, true);
+ }
+
+ WiFi.disconnect(true);
+ delay(100);
+ wifi_scan_obj.StartScan(WIFI_SCAN_OFF, TFT_RED);
+ }
+ }
+
+ delay(2000);
+
+ this->changeMenu(&actionMenu, true);
+ });
+ #endif
+
+
+ // Menu for generating and setting MAC addrs for AP and STA
+ setMacMenu.parentMenu = &wifiGeneralMenu;
+ this->addNodes(&setMacMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(setMacMenu.parentMenu, true);
+ });
+
+ // Generate random MAC for AP
+ this->addNodes(&setMacMenu, "Generate AP MAC", TFTLIME, 0, [this]() {
+ this->changeMenu(&genAPMacMenu, true);
+ wifi_scan_obj.RunGenerateRandomMac(true);
+ });
+
+ // Generate random MAC for AP
+ this->addNodes(&setMacMenu, "Generate STA MAC", TFTCYAN, 0, [this]() {
+ this->changeMenu(&genAPMacMenu, true);
+ wifi_scan_obj.RunGenerateRandomMac(false);
+ });
+
+ // Clone AP MAC to ESP32 for button folks
+ //#ifndef HAS_ILI9341
+ this->addNodes(&setMacMenu, "Clone AP MAC", TFTRED, CLEAR_ICO, [this](){
+ wifiAPMenu.parentMenu = &wifiGeneralMenu;
+
+ // Add the back button
+ wifiAPMenu.list->clear();
+ this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(wifiAPMenu.parentMenu, true);
+ });
+
+ // Populate the menu with buttons
+ for (int i = 0; i < access_points->size(); i++) {
+ // This is the menu node
+ this->addNodes(&wifiAPMenu, access_points->get(i).essid.c_str(), TFTLIME, 255, [this, i](){
+ this->changeMenu(&genAPMacMenu, true);
+ wifi_scan_obj.RunSetMac(access_points->get(i).bssid, true);
+ });
+ }
+ this->changeMenu(&wifiAPMenu, true);
+ });
+
+ this->addNodes(&setMacMenu, "Clone STA MAC", TFTMAGENTA, CLEAR_ICO, [this](){
+ wifiAPMenu.parentMenu = &wifiGeneralMenu;
+
+ // Add the back button
+ wifiAPMenu.list->clear();
+ this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(wifiAPMenu.parentMenu, true);
+ });
+
+ // Populate the menu with buttons
+ for (int i = 0; i < stations->size(); i++) {
+ // This is the menu node
+ this->addNodes(&wifiAPMenu, macToString(stations->get(i).mac).c_str(), TFTMAGENTA, 255, [this, i](){
+ this->changeMenu(&genAPMacMenu, true);
+ wifi_scan_obj.RunSetMac(stations->get(i).mac, false);
+ });
+ }
+ this->changeMenu(&wifiAPMenu, true);
+ });
+ //#endif
+
+ // Menu for generating and setting access point MAC (just goes bacK)
+ genAPMacMenu.parentMenu = &wifiGeneralMenu;
+ this->addNodes(&genAPMacMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(genAPMacMenu.parentMenu, true);
+ });
+
+ // Build generate ssids menu
+ generateSSIDsMenu.parentMenu = &wifiGeneralMenu;
+ this->addNodes(&generateSSIDsMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(generateSSIDsMenu.parentMenu, true);
+ });
+
+ // Build clear ssids menu
+
+ this->addNodes(&clearSSIDsMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(clearSSIDsMenu.parentMenu, true);
+ });
+ clearAPsMenu.parentMenu = &wifiGeneralMenu;
+ this->addNodes(&clearAPsMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(clearAPsMenu.parentMenu, true);
+ });
+
+#ifdef HAS_BT
+ // Build Bluetooth Menu
+ bluetoothMenu.parentMenu = &mainMenu; // Second Menu is third menu parent
+ this->addNodes(&bluetoothMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(bluetoothMenu.parentMenu, true);
+ });
+ this->addNodes(&bluetoothMenu, text_table1[31], TFTYELLOW, SNIFFERS, [this]() {
+ this->changeMenu(&bluetoothSnifferMenu, true);
+ });
+ this->addNodes(&bluetoothMenu, "Bluetooth Attacks", TFTRED, ATTACKS, [this]() {
+ this->changeMenu(&bluetoothAttackMenu, true);
+ });
+
+ // Build bluetooth sniffer Menu
+ bluetoothSnifferMenu.parentMenu = &bluetoothMenu; // Second Menu is third menu parent
+ this->addNodes(&bluetoothSnifferMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(bluetoothSnifferMenu.parentMenu, true);
+ });
+ this->addNodes(&bluetoothSnifferMenu, text_table1[34], TFTGREEN, BLUETOOTH_SNIFF, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(BT_SCAN_ALL, TFT_GREEN);
+ });
+ this->addNodes(&bluetoothSnifferMenu, "Flipper Sniff", TFTORANGE, FLIPPER, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(BT_SCAN_FLIPPER, TFT_ORANGE);
+ });
+ this->addNodes(&bluetoothSnifferMenu, "FindMy Sniff", TFTWHITE, BLUETOOTH_SNIFF, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(BT_SCAN_AIRTAG, TFT_WHITE);
+ });
+ this->addNodes(&bluetoothSnifferMenu, "FindMy Monitor", TFTWHITE, BLUETOOTH_SNIFF, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(BT_SCAN_AIRTAG_MON, TFT_WHITE);
+ });
+ this->addNodes(&bluetoothSnifferMenu, text_table1[35], TFTMAGENTA, CC_SKIMMERS, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(BT_SCAN_SKIMMERS, TFT_MAGENTA);
+ });
+ this->addNodes(&bluetoothSnifferMenu, "Bluetooth Analyzer", TFTCYAN, PACKET_MONITOR, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ this->renderGraphUI(BT_SCAN_ANALYZER);
+ wifi_scan_obj.StartScan(BT_SCAN_ANALYZER, TFT_CYAN);
+ });
+ this->addNodes(&bluetoothSnifferMenu, "Flock Sniff", TFTORANGE, FLOCK, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(BT_SCAN_FLOCK, TFT_ORANGE);
+ });
+ this->addNodes(&bluetoothSnifferMenu, "Meta Detect", TFTWHITE, BLUETOOTH_SNIFF, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(BT_SCAN_RAYBAN, TFT_CYAN);
+ });
+ this->addNodes(&bluetoothSnifferMenu, "Fox Hunt", TFTCYAN, SCANNERS, [this]() {
+ this->buildBluetoothFoxHuntMenu();
});
- this->addNodes(&wifiSnifferMenu, "MAC Monitor", TFTMAGENTA, SCANNERS, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_DETECT_FOLLOW, TFT_MAGENTA);
- });
- this->addNodes(&wifiSnifferMenu, "SAE Commit", TFTLIME, EAPOL, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_SAE_COMMIT, TFT_GREEN);
- });
-
- // Build Wardriving menu
- #ifdef HAS_GPS
- /*wardrivingMenu.parentMenu = &wifiMenu; // Main Menu is second menu parent
- this->addNodes(&wardrivingMenu, text09, TFTLIGHTGREY, NULL, 0, [this]() {
- this->changeMenu(wardrivingMenu.parentMenu, true);
- });*/
- if (gps_obj.getGpsModuleStatus()) {
- this->addNodes(&wifiSnifferMenu, "Wardrive", TFTGREEN, BEACON_SNIFF, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_WAR_DRIVE, TFT_GREEN);
- });
- }
- #endif
- /*#ifdef HAS_GPS
- if (gps_obj.getGpsModuleStatus()) {
- this->addNodes(&wardrivingMenu, "Station Wardrive", TFTORANGE, NULL, PROBE_SNIFF, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_STATION_WAR_DRIVE, TFT_ORANGE);
- });
- }
- #endif*/
-
- // Build WiFi attack menu
- wifiAttackMenu.parentMenu = &wifiMenu; // Main Menu is second menu parent
- this->addNodes(&wifiAttackMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(wifiAttackMenu.parentMenu, true);
- });
- this->addNodes(&wifiAttackMenu, text_table1[50], TFTRED, BEACON_LIST, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_ATTACK_BEACON_LIST, TFT_RED);
- });
- this->addNodes(&wifiAttackMenu, text_table1[51], TFTORANGE, BEACON_SPAM, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_ATTACK_BEACON_SPAM, TFT_ORANGE);
- });
- this->addNodes(&wifiAttackMenu, text1_67, TFTCYAN, FUNNY_BEACON, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_ATTACK_FUNNY_BEACON, TFT_CYAN);
- });
- this->addNodes(&wifiAttackMenu, text_table1[52], TFTYELLOW, RICK_ROLL, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_ATTACK_RICK_ROLL, TFT_YELLOW);
- });
- this->addNodes(&wifiAttackMenu, text_table1[53], TFTRED, PROBE_SNIFF, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_ATTACK_AUTH, TFT_RED);
- });
- this->addNodes(&wifiAttackMenu, "Evil Portal", TFTORANGE, BEACON_SNIFF, [this]() {
-
- wifiAPMenu.list->clear();
- ssidsMenu.list->clear();
-
- wifiAPMenu.parentMenu = &evilPortalMenu;
- ssidsMenu.parentMenu = &evilPortalMenu;
-
- this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(wifiAPMenu.parentMenu, true);
- });
- this->addNodes(&ssidsMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(ssidsMenu.parentMenu, true);
- });
-
- // Get AP list ready
- for (int i = 0; i < access_points->size(); i++) {
- // This is the menu node
- this->addNodes(&wifiAPMenu, access_points->get(i).essid.c_str(), TFTCYAN, 255, [this, i](){
- if (evil_portal_obj.setAP(access_points->get(i).essid)) {
- AccessPoint new_ap = access_points->get(i);
- new_ap.selected = true;
- access_points->set(i, new_ap);
-
- evil_portal_obj.ap_index = i;
-
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_EVIL_PORTAL, TFT_ORANGE);
- wifi_scan_obj.setMac();
- }
- else
- this->changeMenu(&evilPortalMenu, true);
- });
- }
-
- for (int i = 0; i < ssids->size(); i++) {
- // This is the menu node
- this->addNodes(&ssidsMenu, ssids->get(i).essid.c_str(), TFTCYAN, 255, [this, i](){
- if (evil_portal_obj.setAP(ssids->get(i).essid)) {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_EVIL_PORTAL, TFT_ORANGE);
- wifi_scan_obj.setMac();
- }
- else
- this->changeMenu(&evilPortalMenu, true);
- });
- }
- this->changeMenu(&evilPortalMenu, true);
- });
- this->addNodes(&wifiAttackMenu, text_table1[54], TFTRED, DEAUTH_SNIFF, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_ATTACK_DEAUTH, TFT_RED);
- });
- this->addNodes(&wifiAttackMenu, text_table1[57], TFTMAGENTA, BEACON_LIST, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_ATTACK_AP_SPAM, TFT_MAGENTA);
- });
- this->addNodes(&wifiAttackMenu, text_table1[62], TFTRED, DEAUTH_SNIFF, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_ATTACK_DEAUTH_TARGETED, TFT_ORANGE);
- });
-
- this->addNodes(&wifiAttackMenu, "Karma", TFTORANGE, KEYBOARD_ICO, [this](){
- // Add the back button
- selectProbeSSIDsMenu.list->clear();
- this->addNodes(&selectProbeSSIDsMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(&wifiAttackMenu, true);
- });
-
- // Populate the menu with buttons
- for (int i = 0; i < probe_req_ssids->size(); i++) {
- // This is the menu node
- this->addNodes(&selectProbeSSIDsMenu, probe_req_ssids->get(i).essid.c_str(), TFTCYAN, 255, [this, i](){
- if (evil_portal_obj.setAP(probe_req_ssids->get(i).essid)) {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_EVIL_PORTAL, TFT_ORANGE);
- wifi_scan_obj.setMac();
- }
- else
- this->changeMenu(&wifiAttackMenu, true);
- });
- }
- this->changeMenu(&selectProbeSSIDsMenu, true);
- });
-
- this->addNodes(&wifiAttackMenu, "Bad Msg", TFTRED, DEAUTH_SNIFF, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_ATTACK_BAD_MSG, TFT_RED);
- });
- this->addNodes(&wifiAttackMenu, "Bad Msg Targeted", TFTYELLOW, DEAUTH_SNIFF, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_ATTACK_BAD_MSG_TARGETED, TFT_YELLOW);
- });
- this->addNodes(&wifiAttackMenu, "Assoc Sleep", TFTRED, DEAUTH_SNIFF, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_ATTACK_SLEEP, TFT_RED);
- });
- this->addNodes(&wifiAttackMenu, "Assoc Sleep Targ", TFTMAGENTA, DEAUTH_SNIFF, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_ATTACK_SLEEP_TARGETED, TFT_MAGENTA);
- });
- this->addNodes(&wifiAttackMenu, "SAE Commit Flood", TFTLIME, EAPOL, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_ATTACK_SAE_COMMIT, TFT_GREEN);
- });
- this->addNodes(&wifiAttackMenu, "Channel Switch", TFTORANGE, BEACON_LIST, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_ATTACK_CSA, TFT_GREEN);
- });
- this->addNodes(&wifiAttackMenu, "Quiet Time", TFTRED, BEACON_LIST, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_ATTACK_QUIET, TFT_GREEN);
- });
-
- evilPortalMenu.parentMenu = &wifiAttackMenu;
- this->addNodes(&evilPortalMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(evilPortalMenu.parentMenu, true);
- });
- this->addNodes(&evilPortalMenu, "Access Points", TFTGREEN, BEACON_SNIFF, [this]() {
- this->changeMenu(&wifiAPMenu, true);
- });
- this->addNodes(&evilPortalMenu, "User SSIDs", TFTCYAN, PROBE_SNIFF, [this]() {
- this->changeMenu(&ssidsMenu, true);
- });
-
- // Build WiFi General menu
- wifiGeneralMenu.parentMenu = &wifiMenu;
- this->addNodes(&wifiGeneralMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(wifiGeneralMenu.parentMenu, true);
- });
- this->addNodes(&wifiGeneralMenu, text_table1[27], TFTSKYBLUE, GENERATE, [this]() {
- this->changeMenu(&generateSSIDsMenu, true);
- wifi_scan_obj.RunGenerateSSIDs();
- });
-
- //Add Select probe ssid
- this->addNodes(&wifiGeneralMenu, text_table1[65], TFTCYAN, KEYBOARD_ICO, [this]() {
- selectProbeSSIDsMenu.list->clear();
-
- // Add the back button
- this->addNodes(&selectProbeSSIDsMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(&wifiGeneralMenu, true);
-
- // TODO: TBD - Should probe_req_ssids have it´s own life and override ap.config and/or ssids -list for EP?
- // If so, then we should not add selected ssids to ssids list
-
- // Add selected ssid names to ssids list when clicking back button
- if (probe_req_ssids->size() > 0) {
-
- //TODO: TBD - Clear ssids list before adding new ones??
-
- for (int i = 0; i < probe_req_ssids->size(); i++) {
- ProbeReqSsid cur_probe_ssid = probe_req_ssids->get(i);
- if (cur_probe_ssid.selected) {
- bool ssidExists = false;
- for (int i = 0; i < ssids->size(); i++) {
- if (ssids->get(i).essid == cur_probe_ssid.essid) {
- ssidExists = true;
- break;
- }
- }
- if (!ssidExists) {
- wifi_scan_obj.addSSID(cur_probe_ssid.essid);
- }
- }
- }
- }
- });
-
- // Populate the menu with buttons
- for (int i = 0; i < probe_req_ssids->size(); i++) {
- ProbeReqSsid cur_ssid = probe_req_ssids->get(i);
- // This is the menu node
- String button_name = "[" + String(cur_ssid.requests) + "]" + cur_ssid.essid;
- this->addNodes(
- &selectProbeSSIDsMenu,
- button_name.c_str(),
- TFTCYAN,
- 255,
- [this, i]() {
- ProbeReqSsid new_ssid = probe_req_ssids->get(i);
- new_ssid.selected = !probe_req_ssids->get(i).selected;
-
- // Change selection status of menu node
- MenuNode new_node = current_menu->list->get(i + 1);
- new_node.selected = !current_menu->list->get(i + 1).selected;
- current_menu->list->set(i + 1, new_node);
-
- probe_req_ssids->set(i, new_ssid);
- },
- probe_req_ssids->get(i).selected);
- }
- this->changeMenu(&selectProbeSSIDsMenu, true);
- });
-
- clearSSIDsMenu.parentMenu = &wifiGeneralMenu;
-
- #ifdef HAS_ILI9341
- this->addNodes(&wifiGeneralMenu, text_table1[1], TFTNAVY, KEYBOARD_ICO, [this](){
- char ssidBuf[64] = {0};
- bool keep_going = true;
- while (keep_going) {
- display_obj.clearScreen();
- if (keyboardInput(ssidBuf, sizeof(ssidBuf), "Enter SSID")) {
- if (ssidBuf[0] != 0)
- wifi_scan_obj.addSSID(String(ssidBuf));
- for (int i = 0; i < 64; i++)
- ssidBuf[i] = NULL;
- }
- else
- keep_going = false;
- }
-
- this->changeMenu(current_menu);
- });
- #endif
- #if (!defined(HAS_ILI9341) && defined(HAS_BUTTONS))
- this->addNodes(&wifiGeneralMenu, text_table1[1], TFTNAVY, KEYBOARD_ICO, [this](){
- this->changeMenu(&miniKbMenu, true);
- #ifdef HAS_MINI_KB
- this->miniKeyboard(&miniKbMenu);
- #endif
- });
- #endif
- this->addNodes(&wifiGeneralMenu, text_table1[28], TFTSILVER, CLEAR_ICO, [this]() {
- this->changeMenu(&clearSSIDsMenu, true);
- wifi_scan_obj.RunClearSSIDs();
- });
- this->addNodes(&wifiGeneralMenu, text_table1[29], TFTDARKGREY, CLEAR_ICO, [this]() {
- this->changeMenu(&clearAPsMenu, true);
- wifi_scan_obj.RunClearAPs();
- });
- this->addNodes(&wifiGeneralMenu, text_table1[60], TFTBLUE, CLEAR_ICO, [this]() {
- this->changeMenu(&clearAPsMenu, true);
- wifi_scan_obj.RunClearStations();
- });
- //#else // Mini EP HTML select
- this->addNodes(&wifiGeneralMenu, "Select EP HTML File", TFTCYAN, KEYBOARD_ICO, [this](){
- // Add the back button
- htmlMenu.list->clear();
- this->addNodes(&htmlMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(htmlMenu.parentMenu, true);
- });
-
- // Populate the menu with buttons
- for (int i = 0; i < evil_portal_obj.html_files->size(); i++) {
- // This is the menu node
- this->addNodes(&htmlMenu, evil_portal_obj.html_files->get(i).c_str(), TFTCYAN, 255, [this, i](){
- evil_portal_obj.selected_html_index = i;
- evil_portal_obj.target_html_name = evil_portal_obj.html_files->get(evil_portal_obj.selected_html_index);
- Serial.println("Set Evil Portal HTML as " + evil_portal_obj.target_html_name);
- evil_portal_obj.using_serial_html = false;
- this->changeMenu(htmlMenu.parentMenu, true);
- return;
- });
- }
- this->changeMenu(&htmlMenu, true);
- });
-
- //#if (!defined(HAS_ILI9341) && defined(HAS_BUTTONS))
- miniKbMenu.parentMenu = &wifiGeneralMenu;
- #if !defined(MARAUDER_CARDPUTER) && !defined(MARAUDER_CARDPUTER_ADV)
- this->addNodes(&miniKbMenu, "a", TFTCYAN, 0, [this]() {
- this->changeMenu(miniKbMenu.parentMenu, true);
- });
- #endif
- //#endif
-
- htmlMenu.parentMenu = &wifiGeneralMenu;
- this->addNodes(&htmlMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(htmlMenu.parentMenu, true);
- });
-
- // Select APs on Mini
- this->addNodes(&wifiGeneralMenu, "Select APs", TFTNAVY, KEYBOARD_ICO, [this](){
- wifiAPMenu.parentMenu = &wifiGeneralMenu;
- // Add the back button
- wifiAPMenu.list->clear();
- this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(wifiAPMenu.parentMenu, true);
- });
-
- this->addNodes(&wifiAPMenu, "Select ALL", TFTGREEN, 255, [this](){
-
- for (int x = 0; x < access_points->size(); x++) {
- AccessPoint new_ap = access_points->get(x);
- new_ap.selected = !access_points->get(x).selected;
- access_points->set(x, new_ap);
-
- MenuNode new_node = current_menu->list->get(x + 2);
- new_node.selected = !current_menu->list->get(x + 2).selected;
- current_menu->list->set(x + 2, new_node);
- }
-
- this->changeMenu(current_menu, true);
-
- });
-
- // Populate the menu with buttons
- for (int i = 0; i < access_points->size(); i++) {
- // This is the menu node
- this->addNodes(&wifiAPMenu, access_points->get(i).essid.c_str(), TFTCYAN, 255, [this, i](){
- AccessPoint new_ap = access_points->get(i);
- new_ap.selected = !access_points->get(i).selected;
-
- // Change selection status of menu node
- MenuNode new_node = current_menu->list->get(i + 2);
- new_node.selected = !current_menu->list->get(i + 2).selected;
- current_menu->list->set(i + 2, new_node);
-
- access_points->set(i, new_ap);
- }, access_points->get(i).selected);
- }
- this->changeMenu(&wifiAPMenu, true);
- });
-
- this->addNodes(&wifiGeneralMenu, "View AP Info", TFTCYAN, KEYBOARD_ICO, [this](){
- wifiAPMenu.parentMenu = &wifiGeneralMenu;
-
- // Add the back button
- wifiAPMenu.list->clear();
- this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(wifiAPMenu.parentMenu, true);
- });
-
- // Populate the menu with buttons
- for (int i = 0; i < access_points->size(); i++) {
- // This is the menu node
- this->addNodes(&wifiAPMenu, access_points->get(i).essid.c_str(), TFTCYAN, 255, [this, i](){
- this->changeMenu(&apInfoMenu, true);
- wifi_scan_obj.RunAPInfo(i);
- });
- }
- this->changeMenu(&wifiAPMenu, true);
- });
-
- apInfoMenu.parentMenu = &wifiAPMenu;
- this->addNodes(&apInfoMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(apInfoMenu.parentMenu, true);
- });
-
- wifiAPMenu.parentMenu = &wifiGeneralMenu;
- this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(wifiAPMenu.parentMenu, true);
- });
-
- wifiIPMenu.parentMenu = &wifiScannerMenu;
- this->addNodes(&wifiIPMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(wifiIPMenu.parentMenu, true);
- });
-
-
- // Select Stations on Mini v2
- this->addNodes(&wifiGeneralMenu, "Select Stations", TFTCYAN, KEYBOARD_ICO, [this](){
- wifiAPMenu.parentMenu = &wifiGeneralMenu;
-
- wifiAPMenu.list->clear();
- this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(wifiAPMenu.parentMenu, true);
- });
-
- int menu_limit = access_points->size();
-
-
- for (int i = 0; i < menu_limit; i++) {
- wifiStationMenu.list->clear();
- this->addNodes(&wifiAPMenu, access_points->get(i).essid.c_str(), TFTCYAN, 255, [this, i](){
-
- wifiStationMenu.list->clear();
-
- wifiStationMenu.parentMenu = &wifiAPMenu;
-
- // Add back button to the APs
- this->addNodes(&wifiStationMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(wifiStationMenu.parentMenu, true);
- });
-
- this->addNodes(&wifiStationMenu, "Select ALL", TFTGREEN, 255, [this, i](){
-
- for (int y = 0; y < access_points->get(i).stations->size(); y++) {
- int cur_ap_sta_inx = access_points->get(i).stations->get(y);
- Station new_sta = stations->get(cur_ap_sta_inx);
- new_sta.selected = !stations->get(cur_ap_sta_inx).selected;
-
- // Change selection status of menu node
- MenuNode new_node = current_menu->list->get(y + 2);
- new_node.selected = !current_menu->list->get(y + 2).selected;
- current_menu->list->set(y + 2, new_node);
-
- stations->set(cur_ap_sta_inx, new_sta);
- }
-
- this->changeMenu(current_menu, true);
-
- });
-
- // Add the AP's stations to the specific AP menu
- for (int x = 0; x < access_points->get(i).stations->size(); x++) {
- int cur_ap_sta = access_points->get(i).stations->get(x);
-
- this->addNodes(&wifiStationMenu, macToString(stations->get(cur_ap_sta)).c_str(), TFTCYAN, 255, [this, i, cur_ap_sta, x](){
- Station new_sta = stations->get(cur_ap_sta);
- new_sta.selected = !stations->get(cur_ap_sta).selected;
-
- // Change selection status of menu node
- MenuNode new_node = current_menu->list->get(x + 2);
- new_node.selected = !current_menu->list->get(x + 2).selected;
- current_menu->list->set(x + 2, new_node);
-
- stations->set(cur_ap_sta, new_sta);
- }, stations->get(cur_ap_sta).selected);
- }
-
- // Final change menu to the menu of Stations
- this->changeMenu(&wifiStationMenu, true);
-
- }, false);
- }
- this->changeMenu(&wifiAPMenu, true);
- });
-
- this->addNodes(&wifiGeneralMenu, "Join WiFi", TFTWHITE, KEYBOARD_ICO, [this](){
-
- wifiAPMenu.parentMenu = &wifiGeneralMenu;
-
- // Add the back button
- wifiAPMenu.list->clear();
- this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(wifiAPMenu.parentMenu, true);
- });
-
- // Populate the menu with buttons
- for (int i = 0; i < access_points->size(); i++) {
- // This is the menu node
- this->addNodes(&wifiAPMenu, access_points->get(i).essid.c_str(), TFTCYAN, 255, [this, i](){
- // Join WiFi using mini keyboard
- #ifdef HAS_MINI_KB
- this->changeMenu(&miniKbMenu, true);
- String password = this->miniKeyboard(&miniKbMenu, true);
- if (password != "") {
- Serial.println("Using SSID: " + (String)access_points->get(i).essid + " Password: " + (String)password);
- wifi_scan_obj.currentScanMode = LV_JOIN_WIFI;
- wifi_scan_obj.StartScan(LV_JOIN_WIFI, TFT_YELLOW);
- wifi_scan_obj.joinWiFi(access_points->get(i).essid, password);
- this->changeMenu(current_menu, true);
- }
- #endif
-
- // Join WiFi using touch screen keyboard
- #ifdef HAS_TOUCH
- char passwordBuf[64] = {0}; // or prefill with existing SSID
- if (keyboardInput(passwordBuf, sizeof(passwordBuf), "Enter Password")) {
- wifi_scan_obj.joinWiFi(access_points->get(i).essid, String(passwordBuf), true);
- }
-
- this->changeMenu(&wifiGeneralMenu, true);
- #endif
- });
- }
- this->changeMenu(&wifiAPMenu, true);
- });
-
- this->addNodes(&wifiGeneralMenu, "Join Saved WiFi", TFTWHITE, KEYBOARD_ICO, [this](){
- String ssid = settings_obj.loadSetting("ClientSSID");
- String pw = settings_obj.loadSetting("ClientPW");
-
- if ((ssid != "") && (pw != "")) {
- wifi_scan_obj.joinWiFi(ssid, pw, false);
- this->changeMenu(&wifiGeneralMenu, true);
- }
- else {
- wifiAPMenu.parentMenu = &wifiGeneralMenu;
-
- // Add the back button
- wifiAPMenu.list->clear();
- this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(wifiAPMenu.parentMenu, true);
- });
-
- // Populate the menu with buttons
- for (int i = 0; i < access_points->size(); i++) {
- // This is the menu node
- this->addNodes(&wifiAPMenu, access_points->get(i).essid.c_str(), TFTCYAN, 255, [this, i](){
- // Join WiFi using mini keyboard
- #ifdef HAS_MINI_KB
- this->changeMenu(&miniKbMenu, true);
- String password = this->miniKeyboard(&miniKbMenu, true);
- if (password != "") {
- Serial.println("Using SSID: " + (String)access_points->get(i).essid + " Password: " + (String)password);
- wifi_scan_obj.currentScanMode = LV_JOIN_WIFI;
- wifi_scan_obj.StartScan(LV_JOIN_WIFI, TFT_YELLOW);
- wifi_scan_obj.joinWiFi(access_points->get(i).essid, password);
- this->changeMenu(current_menu, true);
- }
- #endif
-
- // Join WiFi using touch screen keyboard
- #ifdef HAS_TOUCH
- char passwordBuf[64] = {0}; // or prefill with existing SSID
- if (keyboardInput(passwordBuf, sizeof(passwordBuf), "Enter Password")) {
- wifi_scan_obj.joinWiFi(access_points->get(i).essid, String(passwordBuf), true);
- }
-
- this->changeMenu(&wifiGeneralMenu, true);
- #endif
- });
- }
- this->changeMenu(&wifiAPMenu, true);
- }
- });
-
- this->addNodes(&wifiGeneralMenu, "Start AP", TFTGREEN, KEYBOARD_ICO, [this](){
- ssidsMenu.parentMenu = &wifiGeneralMenu;
-
- // Add the back button
- ssidsMenu.list->clear();
- this->addNodes(&ssidsMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(ssidsMenu.parentMenu, true);
- });
-
- // Populate the menu with buttons
- for (int i = 0; i < ssids->size(); i++) {
- // This is the menu node
- this->addNodes(&ssidsMenu, ssids->get(i).essid.c_str(), TFTCYAN, 255, [this, i](){
- // Join WiFi using mini keyboard
- #ifdef HAS_MINI_KB
- this->changeMenu(&miniKbMenu, true);
- String password = this->miniKeyboard(&miniKbMenu, true);
- if (password != "") {
- Serial.println("Using SSID: " + (String)ssids->get(i).essid + " Password: " + (String)password);
- wifi_scan_obj.currentScanMode = LV_JOIN_WIFI;
- wifi_scan_obj.StartScan(LV_JOIN_WIFI, TFT_YELLOW);
- wifi_scan_obj.startWiFi(ssids->get(i).essid, password);
- this->changeMenu(current_menu, true);
- }
- #endif
-
- // Join WiFi using touch screen keyboard
- #ifdef HAS_TOUCH
- char passwordBuf[64] = {0}; // or prefill with existing SSID
- if (keyboardInput(passwordBuf, sizeof(passwordBuf), "Enter Password")) {
- Serial.println("Using SSID: " + (String)ssids->get(i).essid + " Password: " + String(passwordBuf));
- wifi_scan_obj.startWiFi(ssids->get(i).essid, String(passwordBuf));
- }
-
- this->changeMenu(&wifiGeneralMenu, false);
- #endif
- });
- }
- this->changeMenu(&ssidsMenu, true);
- });
-
- this->addNodes(&wifiGeneralMenu, "Host AP Info", TFTGREEN, BEACON_SNIFF, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(WIFI_SCAN_DISPLAY_AP_INFO, TFT_GREEN);
- });
-
- wifiStationMenu.parentMenu = &ssidsMenu;
- this->addNodes(&wifiStationMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(wifiStationMenu.parentMenu, true);
- });
-
- this->addNodes(&wifiGeneralMenu, "Set MACs", TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(&setMacMenu, true);
- });
-
- this->addNodes(&wifiGeneralMenu, "Shutdown WiFi", TFTRED, 0, [this]() {
- WiFi.softAPdisconnect(true); // Also shut down the SoftAP if it is running
- WiFi.disconnect(true);
- delay(100);
- wifi_scan_obj.StartScan(WIFI_SCAN_OFF, TFT_RED);
- this->changeMenu(current_menu, true);
- });
-
- #ifdef HAS_DIRECT_UPLOAD
- this->addNodes(&wifiGeneralMenu, "Upload Wardrive Logs", TFTGREEN, 0, [this]() {
- display_obj.clearScreen();
- display_obj.tft.setTextWrap(false);
- display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
- display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
- display_obj.tft.println("Loading...");
-
- this->buildUploadFileMenu();
-
- this->changeMenu(&uploadLogsMenu, true);
- });
-
- uploadAllMenu.parentMenu = &uploadLogsMenu;
- this->addNodes(&uploadAllMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(uploadAllMenu.parentMenu, true);
- });
- this->addNodes(&uploadAllMenu, "WiGLE", TFTLIGHTGREY, 0, [this]() {
- display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
-
- String ssid = settings_obj.loadSetting("ClientSSID");
- String pw = settings_obj.loadSetting("ClientPW");
-
- if ((ssid == "") && (pw == "")) {
- display_obj.clearScreen();
- display_obj.tft.setTextWrap(true);
- display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
- display_obj.tft.println("WiFi Credentials Empty.");
- display_obj.tft.println("Returning...");
- display_obj.tft.setTextWrap(false);
- }
- else {
- display_obj.clearScreen();
- display_obj.showCenterText(String("Connecting to " + ssid).c_str(), TFT_HEIGHT / 2, true);
- if (!wifi_scan_obj.joinWiFi(ssid, pw, false)) {
- display_obj.clearScreen();
- display_obj.tft.setTextWrap(true);
- display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
- display_obj.tft.println("Could not connect to WiFi.");
- display_obj.tft.println("Returning...");
- display_obj.tft.setTextWrap(false);
- }
- else {
- delay(1000);
- for (int i = 0; i < sd_obj.sd_files->size(); i++) {
- if (sd_obj.sd_files->get(i).startsWith("wardrive_") || sd_obj.sd_files->get(i).startsWith("wigle-")) {
- if (!sd_obj.sd_files->get(i).endsWith(".wigle") && !sd_obj.sd_files->get(i).endsWith(".wdg") && !sd_obj.sd_files->get(i).endsWith(".gpx")) {
- Serial.println("Uploading " + sd_obj.sd_files->get(i) + "...");
- if (wifi_scan_obj.uploadFile("/" + sd_obj.sd_files->get(i), true, WIGLE_UPLOAD)) {
- display_obj.clearScreen();
- display_obj.showCenterText("WiGLE OK", TFT_HEIGHT / 2);
- } else {
- display_obj.clearScreen();
- display_obj.showCenterText("WiGLE failed", TFT_HEIGHT / 2);
- }
- }
- }
- }
- WiFi.disconnect(true);
- delay(100);
- wifi_scan_obj.StartScan(WIFI_SCAN_OFF, TFT_RED);
- }
- }
-
- delay(2000);
-
- this->changeMenu(uploadAllMenu.parentMenu, true);
- });
- this->addNodes(&uploadAllMenu, "WDGWars", TFTLIGHTGREY, 0, [this]() {
- String ssid = settings_obj.loadSetting("ClientSSID");
- String pw = settings_obj.loadSetting("ClientPW");
-
- display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
-
- if ((ssid == "") && (pw == "")) {
- display_obj.clearScreen();
- display_obj.tft.setTextWrap(true);
- display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
- display_obj.tft.println("WiFi Credentials Empty.");
- display_obj.tft.println("Returning...");
- display_obj.tft.setTextWrap(false);
- }
- else {
- display_obj.clearScreen();
- display_obj.showCenterText(String("Connecting to " + ssid).c_str(), TFT_HEIGHT / 2, true);
- if (!wifi_scan_obj.joinWiFi(ssid, pw, false)) {
- display_obj.clearScreen();
- display_obj.tft.setTextWrap(true);
- display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
- display_obj.tft.println("Could not connect to WiFi.");
- display_obj.tft.println("Returning...");
- display_obj.tft.setTextWrap(false);
- }
- else {
- delay(1000);
- for (int i = 0; i < sd_obj.sd_files->size(); i++) {
- if (sd_obj.sd_files->get(i).startsWith("wardrive_") || sd_obj.sd_files->get(i).startsWith("wigle-")) {
- if (!sd_obj.sd_files->get(i).endsWith(".wigle") && !sd_obj.sd_files->get(i).endsWith(".wdg") && !sd_obj.sd_files->get(i).endsWith(".gpx")) {
- Serial.println("Uploading " + sd_obj.sd_files->get(i) + "...");
- if (wifi_scan_obj.uploadFile("/" + sd_obj.sd_files->get(i), true, WDG_UPLOAD)) {
- display_obj.clearScreen();
- display_obj.showCenterText("WDG OK", TFT_HEIGHT / 2);
- } else {
- display_obj.clearScreen();
- display_obj.showCenterText("WDG failed", TFT_HEIGHT / 2);
- }
- }
- }
- }
- WiFi.disconnect(true);
- delay(100);
- wifi_scan_obj.StartScan(WIFI_SCAN_OFF, TFT_RED);
- }
- }
-
- delay(2000);
-
- this->changeMenu(uploadAllMenu.parentMenu, true);
- });
- this->addNodes(&uploadAllMenu, "Both", TFTLIGHTGREY, 0, [this]() {
- String ssid = settings_obj.loadSetting("ClientSSID");
- String pw = settings_obj.loadSetting("ClientPW");
-
- display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
-
- if ((ssid == "") && (pw == "")) {
- display_obj.clearScreen();
- display_obj.tft.setTextWrap(true);
- display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
- display_obj.tft.println("WiFi Credentials Empty.");
- display_obj.tft.println("Returning...");
- display_obj.tft.setTextWrap(false);
- }
- else {
- display_obj.clearScreen();
- display_obj.showCenterText(String("Connecting to " + ssid).c_str(), TFT_HEIGHT / 2, true);
- if (!wifi_scan_obj.joinWiFi(ssid, pw, false)) {
- display_obj.clearScreen();
- display_obj.tft.setTextWrap(true);
- display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
- display_obj.tft.println("Could not connect to WiFi.");
- display_obj.tft.println("Returning...");
- display_obj.tft.setTextWrap(false);
- }
- else {
- delay(1000);
- for (int i = 0; i < sd_obj.sd_files->size(); i++) {
- if (sd_obj.sd_files->get(i).startsWith("wardrive_") || sd_obj.sd_files->get(i).startsWith("wigle-")) {
- if (!sd_obj.sd_files->get(i).endsWith(".wigle") && !sd_obj.sd_files->get(i).endsWith(".wdg") && !sd_obj.sd_files->get(i).endsWith(".gpx")) {
- Serial.println("Uploading " + sd_obj.sd_files->get(i) + "...");
- if (wifi_scan_obj.uploadFile("/" + sd_obj.sd_files->get(i), true, BOTH_UPLOAD)) {
- display_obj.clearScreen();
- display_obj.showCenterText("Upload OK", TFT_HEIGHT / 2);
- } else {
- display_obj.clearScreen();
- display_obj.showCenterText("Upload failed", TFT_HEIGHT / 2);
- }
- }
- }
- }
- WiFi.disconnect(true);
- delay(100);
- wifi_scan_obj.StartScan(WIFI_SCAN_OFF, TFT_RED);
- }
- }
-
- delay(2000);
-
- this->changeMenu(uploadAllMenu.parentMenu, true);
- });
-
- deleteAllMenu.parentMenu = &uploadLogsMenu;
- this->addNodes(&deleteAllMenu, "No", TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(deleteAllMenu.parentMenu, true);
- });
- this->addNodes(&deleteAllMenu, "Yes", TFTRED, 0, [this]() {
- display_obj.tft.setTextColor(TFT_ORANGE, TFT_BLACK);
-
- display_obj.clearScreen();
-
- display_obj.showCenterText("Deleting logs...", TFT_HEIGHT / 2, true);
-
- for (int i = 0; i < sd_obj.sd_files->size(); i++) {
- if (sd_obj.sd_files->get(i).startsWith("wardrive_") || sd_obj.sd_files->get(i).startsWith("wigle-")) {
- if (sd_obj.removeFile("/" + sd_obj.sd_files->get(i))) {
- Serial.println("Removed file: " + sd_obj.sd_files->get(i));
- sd_obj.removeFile("/" + sd_obj.sd_files->get(i) + ".wdg");
- sd_obj.removeFile("/" + sd_obj.sd_files->get(i) + ".wigle");
- }
- else {
- Serial.println("Could not remove file: " + sd_obj.sd_files->get(i));
- }
- }
- }
- display_obj.clearScreen();
-
- display_obj.showCenterText("Logs removed", TFT_HEIGHT / 2, true);
-
- delay(2000);
-
- this->buildUploadFileMenu();
-
- this->changeMenu(&uploadLogsMenu, true);
- });
-
- actionMenu.parentMenu = &uploadLogsMenu;
- this->addNodes(&actionMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(actionMenu.parentMenu, true);
- });
- this->addNodes(&actionMenu, "WiGLE", TFTLIGHTGREY, 0, [this]() {
- String ssid = settings_obj.loadSetting("ClientSSID");
- String pw = settings_obj.loadSetting("ClientPW");
-
- display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
-
- if ((ssid == "") && (pw == "")) {
- display_obj.clearScreen();
- display_obj.tft.setTextWrap(true);
- display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
- display_obj.tft.println("WiFi Credentials Empty.");
- display_obj.tft.println("Returning...");
- display_obj.tft.setTextWrap(false);
- }
- else {
- display_obj.clearScreen();
- display_obj.showCenterText(String("Connecting to " + ssid).c_str(), TFT_HEIGHT / 2, true);
- if (!wifi_scan_obj.joinWiFi(ssid, pw, false)) {
- display_obj.clearScreen();
- display_obj.tft.setTextWrap(true);
- display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
- display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
- display_obj.tft.println("Could not connect to WiFi.");
- display_obj.tft.println("Returning...");
- display_obj.tft.setTextWrap(false);
- }
- else {
- delay(1000);
- Serial.println("Uploading " + sd_obj.selected_file_name + "...");
- if (wifi_scan_obj.uploadFile("/" + sd_obj.selected_file_name, true, WIGLE_UPLOAD)) {
- display_obj.clearScreen();
- display_obj.showCenterText("WiGLE OK", TFT_HEIGHT / 2, true);
- } else {
- display_obj.clearScreen();
- display_obj.showCenterText("WiGLE failed", TFT_HEIGHT / 2, true);
- }
-
- WiFi.disconnect(true);
- delay(100);
- wifi_scan_obj.StartScan(WIFI_SCAN_OFF, TFT_RED);
- }
- }
-
- delay(2000);
-
- this->changeMenu(&actionMenu, true);
- });
- this->addNodes(&actionMenu, "WDGWars", TFTLIGHTGREY, 0, [this]() {
- String ssid = settings_obj.loadSetting("ClientSSID");
- String pw = settings_obj.loadSetting("ClientPW");
-
- display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
-
- if ((ssid == "") && (pw == "")) {
- display_obj.clearScreen();
- display_obj.tft.setTextWrap(true);
- display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
- display_obj.tft.println("WiFi Credentials Empty.");
- display_obj.tft.println("Returning...");
- display_obj.tft.setTextWrap(false);
- }
- else {
- display_obj.clearScreen();
- display_obj.showCenterText(String("Connecting to " + ssid).c_str(), TFT_HEIGHT / 2, true);
- if (!wifi_scan_obj.joinWiFi(ssid, pw, false)) {
- display_obj.clearScreen();
- display_obj.tft.setTextWrap(true);
- display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
- display_obj.tft.println("Could not connect to WiFi.");
- display_obj.tft.println("Returning...");
- display_obj.tft.setTextWrap(false);
- }
- else {
- delay(1000);
- Serial.println("Uploading " + sd_obj.selected_file_name + "...");
- if (wifi_scan_obj.uploadFile("/" + sd_obj.selected_file_name, true, WDG_UPLOAD)) {
- display_obj.clearScreen();
- display_obj.showCenterText("WDG OK", TFT_HEIGHT / 2, true);
- } else {
- display_obj.clearScreen();
- display_obj.showCenterText("WDG failed", TFT_HEIGHT / 2, true);
- }
-
- WiFi.disconnect(true);
- delay(100);
- wifi_scan_obj.StartScan(WIFI_SCAN_OFF, TFT_RED);
- }
- }
-
- delay(2000);
-
- this->changeMenu(&actionMenu, true);
- });
- this->addNodes(&actionMenu, "Both", TFTLIGHTGREY, 0, [this]() {
- String ssid = settings_obj.loadSetting("ClientSSID");
- String pw = settings_obj.loadSetting("ClientPW");
-
- display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
-
- if ((ssid == "") && (pw == "")) {
- display_obj.clearScreen();
- display_obj.tft.setTextWrap(true);
- display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
- display_obj.tft.println("WiFi Credentials Empty.");
- display_obj.tft.println("Returning...");
- display_obj.tft.setTextWrap(false);
- }
- else {
- display_obj.clearScreen();
- display_obj.showCenterText(String("Connecting to " + ssid).c_str(), TFT_HEIGHT / 2, true);
- if (!wifi_scan_obj.joinWiFi(ssid, pw, false)) {
- display_obj.clearScreen();
- display_obj.tft.setTextWrap(true);
- display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
- display_obj.tft.println("Could not connect to WiFi.");
- display_obj.tft.println("Returning...");
- display_obj.tft.setTextWrap(false);
- }
- else {
- delay(1000);
- Serial.println("Uploading " + sd_obj.selected_file_name + "...");
- if (wifi_scan_obj.uploadFile("/" + sd_obj.selected_file_name, true, BOTH_UPLOAD)) {
- display_obj.clearScreen();
- display_obj.showCenterText("Upload OK", TFT_HEIGHT / 2, true);
- } else {
- display_obj.clearScreen();
- display_obj.showCenterText("Upload failed", TFT_HEIGHT / 2, true);
- }
-
- WiFi.disconnect(true);
- delay(100);
- wifi_scan_obj.StartScan(WIFI_SCAN_OFF, TFT_RED);
- }
- }
-
- delay(2000);
-
- this->changeMenu(&actionMenu, true);
- });
- #endif
-
-
- // Menu for generating and setting MAC addrs for AP and STA
- setMacMenu.parentMenu = &wifiGeneralMenu;
- this->addNodes(&setMacMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(setMacMenu.parentMenu, true);
- });
-
- // Generate random MAC for AP
- this->addNodes(&setMacMenu, "Generate AP MAC", TFTLIME, 0, [this]() {
- this->changeMenu(&genAPMacMenu, true);
- wifi_scan_obj.RunGenerateRandomMac(true);
- });
-
- // Generate random MAC for AP
- this->addNodes(&setMacMenu, "Generate STA MAC", TFTCYAN, 0, [this]() {
- this->changeMenu(&genAPMacMenu, true);
- wifi_scan_obj.RunGenerateRandomMac(false);
- });
-
- // Clone AP MAC to ESP32 for button folks
- //#ifndef HAS_ILI9341
- this->addNodes(&setMacMenu, "Clone AP MAC", TFTRED, CLEAR_ICO, [this](){
- wifiAPMenu.parentMenu = &wifiGeneralMenu;
-
- // Add the back button
- wifiAPMenu.list->clear();
- this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(wifiAPMenu.parentMenu, true);
- });
-
- // Populate the menu with buttons
- for (int i = 0; i < access_points->size(); i++) {
- // This is the menu node
- this->addNodes(&wifiAPMenu, access_points->get(i).essid.c_str(), TFTLIME, 255, [this, i](){
- this->changeMenu(&genAPMacMenu, true);
- wifi_scan_obj.RunSetMac(access_points->get(i).bssid, true);
- });
- }
- this->changeMenu(&wifiAPMenu, true);
- });
-
- this->addNodes(&setMacMenu, "Clone STA MAC", TFTMAGENTA, CLEAR_ICO, [this](){
- wifiAPMenu.parentMenu = &wifiGeneralMenu;
-
- // Add the back button
- wifiAPMenu.list->clear();
- this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(wifiAPMenu.parentMenu, true);
- });
-
- // Populate the menu with buttons
- for (int i = 0; i < stations->size(); i++) {
- // This is the menu node
- this->addNodes(&wifiAPMenu, macToString(stations->get(i).mac).c_str(), TFTMAGENTA, 255, [this, i](){
- this->changeMenu(&genAPMacMenu, true);
- wifi_scan_obj.RunSetMac(stations->get(i).mac, false);
- });
- }
- this->changeMenu(&wifiAPMenu, true);
- });
- //#endif
-
- // Menu for generating and setting access point MAC (just goes bacK)
- genAPMacMenu.parentMenu = &wifiGeneralMenu;
- this->addNodes(&genAPMacMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(genAPMacMenu.parentMenu, true);
- });
-
- // Build generate ssids menu
- generateSSIDsMenu.parentMenu = &wifiGeneralMenu;
- this->addNodes(&generateSSIDsMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(generateSSIDsMenu.parentMenu, true);
- });
-
- // Build clear ssids menu
-
- this->addNodes(&clearSSIDsMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(clearSSIDsMenu.parentMenu, true);
- });
- clearAPsMenu.parentMenu = &wifiGeneralMenu;
- this->addNodes(&clearAPsMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(clearAPsMenu.parentMenu, true);
- });
-
-#ifdef HAS_BT
- // Build Bluetooth Menu
- bluetoothMenu.parentMenu = &mainMenu; // Second Menu is third menu parent
- this->addNodes(&bluetoothMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(bluetoothMenu.parentMenu, true);
- });
- this->addNodes(&bluetoothMenu, text_table1[31], TFTYELLOW, SNIFFERS, [this]() {
- this->changeMenu(&bluetoothSnifferMenu, true);
- });
- this->addNodes(&bluetoothMenu, "Bluetooth Attacks", TFTRED, ATTACKS, [this]() {
- this->changeMenu(&bluetoothAttackMenu, true);
- });
-
- // Build bluetooth sniffer Menu
- bluetoothSnifferMenu.parentMenu = &bluetoothMenu; // Second Menu is third menu parent
- this->addNodes(&bluetoothSnifferMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(bluetoothSnifferMenu.parentMenu, true);
- });
- this->addNodes(&bluetoothSnifferMenu, text_table1[34], TFTGREEN, BLUETOOTH_SNIFF, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(BT_SCAN_ALL, TFT_GREEN);
- });
- this->addNodes(&bluetoothSnifferMenu, "Flipper Sniff", TFTORANGE, FLIPPER, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(BT_SCAN_FLIPPER, TFT_ORANGE);
- });
- this->addNodes(&bluetoothSnifferMenu, "FindMy Sniff", TFTWHITE, BLUETOOTH_SNIFF, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(BT_SCAN_AIRTAG, TFT_WHITE);
- });
- this->addNodes(&bluetoothSnifferMenu, "FindMy Monitor", TFTWHITE, BLUETOOTH_SNIFF, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(BT_SCAN_AIRTAG_MON, TFT_WHITE);
- });
- this->addNodes(&bluetoothSnifferMenu, text_table1[35], TFTMAGENTA, CC_SKIMMERS, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(BT_SCAN_SKIMMERS, TFT_MAGENTA);
- });
- this->addNodes(&bluetoothSnifferMenu, "Bluetooth Analyzer", TFTCYAN, PACKET_MONITOR, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- this->renderGraphUI(BT_SCAN_ANALYZER);
- wifi_scan_obj.StartScan(BT_SCAN_ANALYZER, TFT_CYAN);
- });
- this->addNodes(&bluetoothSnifferMenu, "Flock Sniff", TFTORANGE, FLOCK, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(BT_SCAN_FLOCK, TFT_ORANGE);
- });
- this->addNodes(&bluetoothSnifferMenu, "Meta Detect", TFTWHITE, BLUETOOTH_SNIFF, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(BT_SCAN_RAYBAN, TFT_CYAN);
- });
- this->addNodes(&bluetoothSnifferMenu, "Fox Hunt", TFTCYAN, SCANNERS, [this]() {
- this->buildBluetoothFoxHuntMenu();
- });
-
- // Bluetooth Attack menu
- bluetoothAttackMenu.parentMenu = &bluetoothMenu; // Second Menu is third menu parent
- this->addNodes(&bluetoothAttackMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(bluetoothAttackMenu.parentMenu, true);
- });
- this->addNodes(&bluetoothAttackMenu, "Sour Apple", TFTGREEN, DEAUTH_SNIFF, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(BT_ATTACK_SOUR_APPLE, TFT_GREEN);
- });
- this->addNodes(&bluetoothAttackMenu, "Apple Juice", TFTYELLOW, DEAUTH_SNIFF, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(BT_ATTACK_APPLE_JUICE, TFT_YELLOW);
- });
- this->addNodes(&bluetoothAttackMenu, "Swiftpair Spam", TFTCYAN, KEYBOARD_ICO, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(BT_ATTACK_SWIFTPAIR_SPAM, TFT_CYAN);
- });
- this->addNodes(&bluetoothAttackMenu, "Samsung BLE Spam", TFTRED, GENERAL_APPS, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(BT_ATTACK_SAMSUNG_SPAM, TFT_RED);
- });
- this->addNodes(&bluetoothAttackMenu, "Google BLE Spam", TFTPURPLE, LANGUAGE, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(BT_ATTACK_GOOGLE_SPAM, TFT_PURPLE);
- });
- this->addNodes(&bluetoothAttackMenu, "Flipper BLE Spam", TFTORANGE, FLIPPER, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(BT_ATTACK_FLIPPER_SPAM, TFT_ORANGE);
- });
- this->addNodes(&bluetoothAttackMenu, "BLE Spam All", TFTMAGENTA, DEAUTH_SNIFF, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(BT_ATTACK_SPAM_ALL, TFT_MAGENTA);
- });
-
-#endif
-
- //#ifndef HAS_ILI9341
- #ifdef HAS_BT
- this->addNodes(&bluetoothAttackMenu, "Spoof Airtag", TFTWHITE, ATTACKS, [this](){
- wifiAPMenu.parentMenu = &bluetoothAttackMenu;
-
- // Clear nodes and add back button
- wifiAPMenu.list->clear();
- this->addNodes(&wifiAPMenu, text09, TFT_LIGHTGREY, 0, [this]() {
- this->changeMenu(wifiAPMenu.parentMenu, true);
- });
-
- // Add buttons for all airtags
- // Find out how big our menu is going to be
- int menu_limit;
- if (airtags->size() <= BUTTON_ARRAY_LEN)
- menu_limit = airtags->size();
- else
- menu_limit = BUTTON_ARRAY_LEN;
-
- // Create the menu nodes for all of the list items
- for (int i = 0; i < menu_limit; i++) {
- this->addNodes(&wifiAPMenu, airtags->get(i).mac.c_str(), TFTWHITE, BLUETOOTH, [this, i](){
- AirTag new_at = airtags->get(i);
- new_at.selected = true;
-
- airtags->set(i, new_at);
-
- // Set all other airtags to "Not Selected"
- for (int x = 0; x < airtags->size(); x++) {
- if (x != i) {
- AirTag new_atx = airtags->get(x);
- new_atx.selected = false;
- airtags->set(x, new_atx);
- }
- }
-
- // Start the spoof
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(BT_SPOOF_AIRTAG, TFT_WHITE);
-
- });
- }
- this->changeMenu(&wifiAPMenu, true);
- });
-
- #ifdef HAS_NIMBLE_2
- this->addNodes(&bluetoothAttackMenu, "FindMy Sound", TFTCYAN, ATTACKS, [this](){
- wifiAPMenu.parentMenu = &bluetoothAttackMenu;
-
- // Clear nodes and add back button
- wifiAPMenu.list->clear();
- this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(wifiAPMenu.parentMenu, true);
- });
-
- /*this->addNodes(&wifiAPMenu, "Live", TFTMAGENTA, 0, [this]() {
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.StartScan(BT_ATTACK_FINDMY_LIVE, TFT_RED);
- });*/
-
- int menu_limit = airtags->size();
-
- // Create the menu nodes for all of the list items
- for (int i = 0; i < menu_limit; i++) {
- uint8_t node_color = rssiToMenuColor(airtags->get(i).rssi);
- String node_name = String(airtags->get(i).rssi) + " " + airtags->get(i).mac;
- this->addNodes(&wifiAPMenu, node_name.c_str(), node_color, BLUETOOTH, [this, i](){
- AirTag new_at = airtags->get(i);
- new_at.selected = true;
- new_at.connectable = true;
-
- airtags->set(i, new_at);
-
- // Set all other airtags to "Not Selected"
- for (int x = 0; x < airtags->size(); x++) {
- if (x != i) {
- AirTag new_atx = airtags->get(x);
- new_atx.selected = false;
- airtags->set(x, new_atx);
- }
- }
-
- // Start the spoof
- display_obj.clearScreen();
- this->drawStatusBar();
- wifi_scan_obj.executeFindMySound(true);
- delay(2000);
- this->changeMenu(&wifiAPMenu, true);
- });
- }
- this->changeMenu(&wifiAPMenu, true);
- });
- #endif
-
- wifiAPMenu.parentMenu = &bluetoothAttackMenu;
- this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(wifiAPMenu.parentMenu, true);
- });
-
- wifiAPMenu.parentMenu = &bluetoothAttackMenu;
- this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(wifiAPMenu.parentMenu, true);
- });
- #endif
-
- //#endif
-
- // Device menu
- deviceMenu.parentMenu = &mainMenu;
- this->addNodes(&deviceMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(deviceMenu.parentMenu, true);
- });
-
- #ifdef HAS_SD
- if (sd_obj.supported) {
-
- sdDeleteMenu.parentMenu = &deviceMenu;
-
- this->addNodes(&deviceMenu, "Update Firmware", TFTORANGE, SD_UPDATE, [this]() {
- display_obj.clearScreen();
- display_obj.tft.setTextWrap(false);
- display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
- display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
- display_obj.tft.println("Loading...");
-
- // Clear menu and lists
- this->buildSDFileMenu(true);
-
- this->changeMenu(&sdDeleteMenu, true);
- });
- }
- #endif
-
- this->addNodes(&deviceMenu, "Save/Load Files", TFTCYAN, SD_UPDATE, [this]() {
- this->changeMenu(&saveFileMenu, true);
- });
-
- #ifndef HAS_MINI_SCREEN
- this->addNodes(&deviceMenu, "Brightness", TFTYELLOW, BRIGHTNESS, [this]() {
- this->brightnessMode();
- });
- #endif
-
- this->addNodes(&deviceMenu, text_table1[17], TFTWHITE, DEVICE_INFO, [this]() {
- wifi_scan_obj.currentScanMode = SHOW_INFO;
- this->changeMenu(&infoMenu, true);
- wifi_scan_obj.RunInfo();
- });
- this->addNodes(&deviceMenu, text08, TFTBLUE, SETTINGS, [this]() {
- this->changeMenu(&settingsMenu, true);
- });
-
- #ifdef HAS_SD
- if (sd_obj.supported) {
-
- sdDeleteMenu.parentMenu = &deviceMenu;
-
- this->addNodes(&deviceMenu, "Delete SD Files", TFTCYAN, SD_UPDATE, [this]() {
- display_obj.clearScreen();
- display_obj.tft.setTextWrap(false);
- display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
- display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
- display_obj.tft.println("Loading...");
-
- // Clear menu and lists
- this->buildSDFileMenu();
-
- this->changeMenu(&sdDeleteMenu, true);
- });
- }
- #endif
-
- // Save Files Menu
- saveFileMenu.parentMenu = &deviceMenu;
- this->addNodes(&saveFileMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(saveFileMenu.parentMenu, true);
- });
- this->addNodes(&saveFileMenu, "Save SSIDs", TFTCYAN, SD_UPDATE, [this]() {
- this->changeMenu(&saveSSIDsMenu, true);
- wifi_scan_obj.RunSaveSSIDList(true);
- });
- this->addNodes(&saveFileMenu, "Load SSIDs", TFTSKYBLUE, SD_UPDATE, [this]() {
- this->changeMenu(&loadSSIDsMenu, true);
- wifi_scan_obj.RunLoadSSIDList();
- });
- this->addNodes(&saveFileMenu, "Save APs", TFTNAVY, SD_UPDATE, [this]() {
- this->changeMenu(&saveAPsMenu, true);
- wifi_scan_obj.RunSaveAPList();
- });
- this->addNodes(&saveFileMenu, "Load APs", TFTBLUE, SD_UPDATE, [this]() {
- this->changeMenu(&loadAPsMenu, true);
- wifi_scan_obj.RunLoadAPList();
- });
- this->addNodes(&saveFileMenu, "Save Airtags", TFTWHITE, SD_UPDATE, [this]() {
- this->changeMenu(&saveAPsMenu, true);
- wifi_scan_obj.RunSaveATList();
- });
- this->addNodes(&saveFileMenu, "Load Airtags", TFTWHITE, SD_UPDATE, [this]() {
- this->changeMenu(&loadAPsMenu, true);
- wifi_scan_obj.RunLoadATList();
- });
-
- saveSSIDsMenu.parentMenu = &saveFileMenu;
- this->addNodes(&saveSSIDsMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(saveSSIDsMenu.parentMenu, true);
- });
-
- loadSSIDsMenu.parentMenu = &saveFileMenu;
- this->addNodes(&loadSSIDsMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(loadSSIDsMenu.parentMenu, true);
- });
-
- saveAPsMenu.parentMenu = &saveFileMenu;
- this->addNodes(&saveAPsMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(saveAPsMenu.parentMenu, true);
- });
-
- loadAPsMenu.parentMenu = &saveFileMenu;
- this->addNodes(&loadAPsMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(loadAPsMenu.parentMenu, true);
- });
-
- saveATsMenu.parentMenu = &saveFileMenu;
- this->addNodes(&saveATsMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(saveATsMenu.parentMenu, true);
- });
-
- loadATsMenu.parentMenu = &saveFileMenu;
- this->addNodes(&loadATsMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(loadATsMenu.parentMenu, true);
- });
-
- // GPS Menu
- #ifdef HAS_GPS
- if (gps_obj.getGpsModuleStatus()) {
- gpsMenu.parentMenu = &mainMenu; // Main Menu is second menu parent
-
- this->addNodes(&gpsMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(gpsMenu.parentMenu, true);
- });
-
- this->addNodes(&gpsMenu, "GPS Data", TFTRED, GPS_MENU, [this]() {
- wifi_scan_obj.currentScanMode = WIFI_SCAN_GPS_DATA;
- this->changeMenu(&gpsInfoMenu, true);
- wifi_scan_obj.StartScan(WIFI_SCAN_GPS_DATA, TFT_CYAN);
- });
-
- this->addNodes(&gpsMenu, "NMEA Stream", TFTORANGE, GPS_MENU, [this]() {
- wifi_scan_obj.currentScanMode = WIFI_SCAN_GPS_NMEA;
- this->changeMenu(&gpsInfoMenu, true);
- wifi_scan_obj.StartScan(WIFI_SCAN_GPS_NMEA, TFT_ORANGE);
- });
-
- this->addNodes(&gpsMenu, "GPS Tracker", TFTGREEN, GPS_MENU, [this]() {
- wifi_scan_obj.currentScanMode = GPS_TRACKER;
- this->changeMenu(&gpsInfoMenu, true);
- wifi_scan_obj.StartScan(GPS_TRACKER, TFT_CYAN);
- });
-
- this->addNodes(&gpsMenu, "GPS POI", TFTCYAN, GPS_MENU, [this]() {
- wifi_scan_obj.StartScan(GPS_POI, TFT_CYAN);
- wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF;
- this->changeMenu(&gpsPOIMenu, true);
- });
-
- // GPS POI Menu
- gpsPOIMenu.parentMenu = &gpsMenu;
- this->addNodes(&gpsPOIMenu, text09, TFTLIGHTGREY, 0, [this]() {
- wifi_scan_obj.currentScanMode = GPS_POI;
- wifi_scan_obj.StartScan(WIFI_SCAN_OFF);
- this->changeMenu(gpsPOIMenu.parentMenu, true);
- });
- this->addNodes(&gpsPOIMenu, "Mark POI", TFTCYAN, GPS_MENU, [this]() {
- wifi_scan_obj.currentScanMode = GPS_POI;
- display_obj.tft.setCursor(0, TFT_HEIGHT / 2);
- display_obj.clearScreen();
- if (wifi_scan_obj.RunGPSInfo(true, false, true))
- display_obj.showCenterText("POI Logged", TFT_HEIGHT / 2);
- else
- display_obj.showCenterText("POI Log Failed", TFT_HEIGHT / 2);
- wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF;
- delay(2000);
- this->changeMenu(&gpsPOIMenu, true);
- });
-
- // GPS Info Menu
- gpsInfoMenu.parentMenu = &gpsMenu;
- this->addNodes(&gpsInfoMenu, text09, TFTLIGHTGREY, 0, [this]() {
- if(wifi_scan_obj.currentScanMode != GPS_TRACKER)
- wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF;
- wifi_scan_obj.StartScan(WIFI_SCAN_OFF);
- this->changeMenu(gpsInfoMenu.parentMenu, true);
- });
- }
- #endif
-
- // Settings menu
- // Device menu
- settingsMenu.parentMenu = &deviceMenu;
- this->addNodes(&settingsMenu, text09, TFTLIGHTGREY, 0, [this]() {
- changeMenu(settingsMenu.parentMenu, true);
- });
- for (int i = 0; i < settings_obj.getNumberSettings(); i++) {
- String settingName = settings_obj.setting_index_to_name(i);
- const char* type = this->callSetting(settingName.c_str());
- if (type && strcmp(type, "bool") == 0) {
- this->addNodes(&settingsMenu, settingName.c_str(), TFTLIGHTGREY, SETTINGS, [this, i, settingName]() {
- settings_obj.toggleSetting(settingName.c_str());
- this->callSetting(settingName.c_str());
- this->changeMenu(&specSettingMenu, true);
- this->displaySetting(settingName.c_str(), &settingsMenu, i + 1);
- wifi_scan_obj.force_pmkid = settings_obj.loadSetting(text_table4[5]);
- wifi_scan_obj.force_probe = settings_obj.loadSetting(text_table4[6]);
- wifi_scan_obj.save_pcap = settings_obj.loadSetting(text_table4[7]);
- wifi_scan_obj.ep_deauth = settings_obj.loadSetting("EPDeauth");
- wifi_scan_obj.channel_hop = settings_obj.loadSetting("ChanHop");
- }, settings_obj.loadSetting(settingName.c_str()));
- }
- }
-
- Serial.println("Finished settings nodes");
-
- // Specific setting menu
- specSettingMenu.parentMenu = &settingsMenu;
- addNodes(&specSettingMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(specSettingMenu.parentMenu, true);
- });
-
- // Web Update
- updateMenu.parentMenu = &deviceMenu;
-
- // Failed update menu
- failedUpdateMenu.parentMenu = &deviceMenu;
- this->addNodes(&failedUpdateMenu, text09, TFTLIGHTGREY, 0, [this]() {
- wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF;
- this->changeMenu(failedUpdateMenu.parentMenu, true);
- });
-
- // Device info menu
- infoMenu.parentMenu = &deviceMenu;
- this->addNodes(&infoMenu, text09, TFTLIGHTGREY, 0, [this]() {
- wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF;
- this->changeMenu(infoMenu.parentMenu, true);
- });
-
- Serial.println("Changing to main menu...");
-
- // Set the current menu to the mainMenu
- this->changeMenu(&mainMenu, true);
-
- this->initTime = millis();
-}
-
-//#if (!defined(HAS_ILI9341) && defined(HAS_BUTTONS))
-#ifdef HAS_MINI_KB
- String MenuFunctions::miniKeyboard(Menu * targetMenu, bool do_pass) {
- // Prepare a char array and reset temp SSID string
- extern LinkedList* ssids;
-
- String ret_val = "";
-
- bool pressed = true;
-
- wifi_scan_obj.current_mini_kb_ssid = "";
-
- #ifdef HAS_MINI_KB
- if (c_btn.isHeld()) {
- while (!c_btn.justReleased())
- delay(1);
- }
- #endif
-
- int str_len = wifi_scan_obj.alfa.length() + 1;
-
- char char_array[str_len];
-
- wifi_scan_obj.alfa.toCharArray(char_array, str_len);
-
- #ifdef HAS_TOUCH
- uint16_t t_x = 0, t_y = 0;
-
- #endif
-
- // Button loop until hold center button
- #ifdef HAS_BUTTONS
- //#if !(defined(MARAUDER_V6) || defined(MARAUDER_V6_1) || defined(MARAUDER_CYD_MICRO))
- while(true) {
- // Keyboard functions for switch hardware
- #ifdef HAS_MINI_KB
- // Cycle char previous
- #ifdef HAS_L
- if ((l_btn.justPressed()) || (l_btn.isHeld())) {
- pressed = true;
- if (this->mini_kb_index > 0)
- this->mini_kb_index--;
- else
- this->mini_kb_index = str_len - 2;
-
- targetMenu->list->set(0, MenuNode{String(char_array[this->mini_kb_index]).c_str(), false, TFTCYAN, 0, true, NULL});
- this->buildButtons(targetMenu);
-
- while (!l_btn.justReleased()) {
- l_btn.justPressed();
- if (!l_btn.isHeld())
- delay(1);
- else
- break;
- }
- }
- #endif
-
- // Cycle char next
- #ifdef HAS_R
- if ((r_btn.justPressed()) || (r_btn.isHeld())) {
- pressed = true;
- if (this->mini_kb_index < str_len - 2)
- this->mini_kb_index++;
- else
- this->mini_kb_index = 0;
-
- targetMenu->list->set(0, MenuNode{String(char_array[this->mini_kb_index]).c_str(), false, TFTCYAN, 0, true, NULL});
- this->buildButtons(targetMenu, 0, &char_array[this->mini_kb_index]);
-
- while (!r_btn.justReleased()) {
- r_btn.justPressed();
- if (!r_btn.isHeld())
- delay(1);
- else
- break;
- }
- }
- #endif
-
- //// 5-WAY SWITCH STUFF
- // Add character
- #if (defined(HAS_D) && defined(HAS_R))
- if (d_btn.justPressed()) {
- pressed = true;
- wifi_scan_obj.current_mini_kb_ssid.concat(String(char_array[this->mini_kb_index]).c_str());
- while (!d_btn.justReleased())
- delay(1);
- }
- #endif
-
- // Remove character
- #if (defined(HAS_U) && defined(HAS_L))
- if (u_btn.justPressed()) {
- pressed = true;
- wifi_scan_obj.current_mini_kb_ssid.remove(wifi_scan_obj.current_mini_kb_ssid.length() - 1);
- while (!u_btn.justReleased())
- delay(1);
- }
- #endif
-
- //// PARTIAL SWITCH STUFF
- // Advance char or add char
- #if (defined(HAS_D) && !defined(HAS_R))
- if (d_btn.justPressed()) {
- bool was_held = false;
- pressed = true;
- while(!d_btn.justReleased()) {
- d_btn.justPressed();
-
- // Add letter to string
- if (d_btn.isHeld()) {
- wifi_scan_obj.current_mini_kb_ssid.concat(String(char_array[this->mini_kb_index]).c_str());
- was_held = true;
- break;
- }
- }
- if (!was_held) {
- if (this->mini_kb_index < str_len - 2)
- this->mini_kb_index++;
- else
- this->mini_kb_index = 0;
-
- targetMenu->list->set(0, MenuNode{String(char_array[this->mini_kb_index]).c_str(), false, TFTCYAN, 0, true, NULL});
- this->buildButtons(targetMenu, 0, &char_array[this->mini_kb_index]);
- }
- }
- #endif
-
- // Prev char or remove char
- #if (defined(HAS_U) && !defined(HAS_L))
- if (u_btn.justPressed()) {
- bool was_held = false;
- pressed = true;
- while(!u_btn.justReleased()) {
- u_btn.justPressed();
-
- // Remove letter from string
- if (u_btn.isHeld()) {
- wifi_scan_obj.current_mini_kb_ssid.remove(wifi_scan_obj.current_mini_kb_ssid.length() - 1);
- was_held = true;
- break;
- }
- }
- if (!was_held) {
- if (this->mini_kb_index > 0)
- this->mini_kb_index--;
- else
- this->mini_kb_index = str_len - 2;
-
- targetMenu->list->set(0, MenuNode{String(char_array[this->mini_kb_index]).c_str(), false, TFTCYAN, 0, true, NULL});
- this->buildButtons(targetMenu);
- }
- }
- #endif
-
- // Add SSID
- #if defined(HAS_C) && !defined(MARAUDER_CARDPUTER) && !defined(MARAUDER_CARDPUTER_ADV)
- if (c_btn.justPressed()) {
- while (!c_btn.justReleased()) {
- c_btn.justPressed(); // Need to continue updating button hold status. My shitty library.
-
- // Exit
- if (c_btn.isHeld()) {
- this->changeMenu(targetMenu->parentMenu);
- return wifi_scan_obj.current_mini_kb_ssid;
- }
- delay(1);
- }
-
- if (!do_pass) {
- // If we have a string, add it to list of SSIDs
- if (wifi_scan_obj.current_mini_kb_ssid != "") {
- pressed = true;
- ssid s = {wifi_scan_obj.current_mini_kb_ssid, random(1, 12), {random(256), random(256), random(256), random(256), random(256), random(256)}, false};
- ssids->unshift(s);
- wifi_scan_obj.current_mini_kb_ssid = "";
- }
- }
- }
- #endif
- #endif
-
- #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
- for (int i = 0; i < 95; i++) {
- if ((M5CardputerKeyboard._ascii_list[i] != '(') &&
- (M5CardputerKeyboard._ascii_list[i] != '`')) {
- if (this->isKeyPressed(M5CardputerKeyboard._ascii_list[i])) {
- pressed = true;
- wifi_scan_obj.current_mini_kb_ssid.concat(M5CardputerKeyboard._ascii_list[i]);
- }
- if (this->isKeyPressed(KEY_BACKSPACE)) {
- pressed = true;
- wifi_scan_obj.current_mini_kb_ssid.remove(wifi_scan_obj.current_mini_kb_ssid.length() - 1);
- }
- }
- }
-
- if (!do_pass) {
- if (this->isKeyPressed('`')) {
- this->changeMenu(targetMenu->parentMenu, true);
- return wifi_scan_obj.current_mini_kb_ssid;
- }
-
- if (this->isKeyPressed('(')) {
- if (!do_pass) {
- if (wifi_scan_obj.current_mini_kb_ssid != "") {
- pressed = true;
- ssid s = {wifi_scan_obj.current_mini_kb_ssid, random(1, 12), {random(256), random(256), random(256), random(256), random(256), random(256)}, false};
- ssids->unshift(s);
- wifi_scan_obj.current_mini_kb_ssid = "";
- }
- }
- }
- }
- else {
- if (this->isKeyPressed('(')) {
- this->changeMenu(targetMenu->parentMenu, true);
- return wifi_scan_obj.current_mini_kb_ssid;
- }
-
- if (this->isKeyPressed('`')) {
- this->changeMenu(targetMenu->parentMenu, true);
- return "";
- }
- }
-
- #endif
-
- // Keyboard functions for touch hardware
- #ifdef HAS_TOUCH
- bool touched = display_obj.updateTouch(&t_x, &t_y);
-
- uint8_t menu_button = display_obj.menuButton(&t_x, &t_y, touched);
-
- // Cycle char previous
- if (menu_button == UP_BUTTON) {
- pressed = true;
- if (this->mini_kb_index > 0)
- this->mini_kb_index--;
- else
- this->mini_kb_index = str_len - 2;
-
- targetMenu->list->set(0, MenuNode{String(char_array[this->mini_kb_index]).c_str(), false, TFTCYAN, 0, true, NULL});
- this->buildButtons(targetMenu);
- while (display_obj.updateTouch(&t_x, &t_y) > 0)
- delay(1);
- display_obj.menuButton(&t_x, &t_y, display_obj.updateTouch(&t_x, &t_y));
- }
-
- // Cycle char next
- if (menu_button == DOWN_BUTTON) {
- pressed = true;
- if (this->mini_kb_index < str_len - 2)
- this->mini_kb_index++;
- else
- this->mini_kb_index = 0;
-
- targetMenu->list->set(0, MenuNode{String(char_array[this->mini_kb_index]).c_str(), false, TFTCYAN, 0, true, NULL});
- this->buildButtons(targetMenu, 0, &char_array[this->mini_kb_index]);
- while (display_obj.updateTouch(&t_x, &t_y) > 0)
- delay(1);
- display_obj.menuButton(&t_x, &t_y, display_obj.updateTouch(&t_x, &t_y));
- }
-
- //// 5-WAY SWITCH STUFF
- // Add character when select button is pressed
- if (menu_button == SELECT_BUTTON) {
- pressed = true;
- wifi_scan_obj.current_mini_kb_ssid.concat(String(char_array[this->mini_kb_index]).c_str());
- while (display_obj.updateTouch(&t_x, &t_y) > 0)
- delay(1);
- display_obj.menuButton(&t_x, &t_y, display_obj.updateTouch(&t_x, &t_y));
- }
-
- // Remove character when select button is held
- if ((display_obj.isTouchHeld()) && (display_obj.menuButton(&t_x, &t_y, touched, true) == SELECT_BUTTON)) {
- pressed = true;
- wifi_scan_obj.current_mini_kb_ssid.remove(wifi_scan_obj.current_mini_kb_ssid.length() - 1);
- while (display_obj.menuButton(&t_x, &t_y, display_obj.updateTouch(&t_x, &t_y)) < 0)
- delay(1);
- }
-
- //// PARTIAL SWITCH STUFF
- // Advance char or add char
- #if (defined(HAS_D) && !defined(HAS_R))
- if (d_btn.justPressed()) {
- bool was_held = false;
- pressed = true;
- while(!d_btn.justReleased()) {
- d_btn.justPressed();
-
- // Add letter to string
- if (d_btn.isHeld()) {
- wifi_scan_obj.current_mini_kb_ssid.concat(String(char_array[this->mini_kb_index]).c_str());
- was_held = true;
- break;
- }
- }
- if (!was_held) {
- if (this->mini_kb_index < str_len - 2)
- this->mini_kb_index++;
- else
- this->mini_kb_index = 0;
-
- targetMenu->list->set(0, MenuNode{String(char_array[this->mini_kb_index]).c_str(), false, TFTCYAN, 0, true, NULL});
- this->buildButtons(targetMenu, 0, &char_array[this->mini_kb_index]);
- }
- }
- #endif
-
- // Prev char or remove char
- #if (defined(HAS_U) && !defined(HAS_L))
- if (u_btn.justPressed()) {
- bool was_held = false;
- pressed = true;
- while(!u_btn.justReleased()) {
- u_btn.justPressed();
-
- // Remove letter from string
- if (u_btn.isHeld()) {
- wifi_scan_obj.current_mini_kb_ssid.remove(wifi_scan_obj.current_mini_kb_ssid.length() - 1);
- was_held = true;
- break;
- }
- }
- if (!was_held) {
- if (this->mini_kb_index > 0)
- this->mini_kb_index--;
- else
- this->mini_kb_index = str_len - 2;
-
- targetMenu->list->set(0, MenuNode{String(char_array[this->mini_kb_index]).c_str(), false, TFTCYAN, 0, true, NULL});
- this->buildButtons(targetMenu);
- }
- }
- #endif
-
- // Exit if UP button is held
- if ((display_obj.isTouchHeld()) && (display_obj.menuButton(&t_x, &t_y, touched, true) == UP_BUTTON)) {
- display_obj.clearScreen();
- while (display_obj.menuButton(&t_x, &t_y, display_obj.updateTouch(&t_x, &t_y)) < 0)
- delay(1);
-
- // Reset the touch keys so we don't activate the keys when we go back
- display_obj.menuButton(&t_x, &t_y, display_obj.updateTouch(&t_x, &t_y));
- this->changeMenu(targetMenu->parentMenu, true);
- return wifi_scan_obj.current_mini_kb_ssid;
- }
-
- // If the screen is touched but none of the keys are used, don't refresh display
- if (menu_button < 0)
- pressed = false;
-
- #endif
-
- // Display info on screen
- if (pressed) {
- this->displayCurrentMenu();
- display_obj.tft.setTextWrap(false);
- display_obj.tft.fillRect(0, SCREEN_HEIGHT / 3, SCREEN_WIDTH, STATUS_BAR_WIDTH, TFT_BLACK);
- display_obj.tft.fillRect(0, SCREEN_HEIGHT / 3 + TEXT_HEIGHT * 2, SCREEN_WIDTH, STATUS_BAR_WIDTH, TFT_BLACK);
- display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
- display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
- display_obj.tft.println(wifi_scan_obj.current_mini_kb_ssid + "\n");
- display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK);
-
- display_obj.tft.println(ssids->get(0).essid);
-
- display_obj.tft.setTextColor(TFT_ORANGE, TFT_BLACK);
- #ifdef HAS_MINI_KB
- #if !defined(MARAUDER_CARDPUTER) && !defined(MARAUDER_CARDPUTER_ADV)
- display_obj.tft.println("U/D - Rem/Add Char");
- display_obj.tft.println("L/R - Prev/Nxt Char");
- #endif
- if (!do_pass) {
- #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
- display_obj.tft.println("Enter - Save");
- display_obj.tft.println("Esc - Exit");
- #else
- display_obj.tft.println("C - Save");
- display_obj.tft.println("C(Hold) - Exit");
- #endif
- }
- else {
- #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
- display_obj.tft.println("Enter - Enter");
- #else
- display_obj.tft.println("C(Hold) - Enter");
- #endif
- }
- #endif
-
- #ifdef HAS_TOUCH
- display_obj.tft.println("U/D - Prev/Nxt Char");
- display_obj.tft.println("C - Add Char");
- display_obj.tft.println("C(Hold) - Rem Char");
- display_obj.tft.println("U(Hold) - Enter");
- #endif
- pressed = false;
- }
- }
- //#endif
- #endif
- }
-#endif
-
-void MenuFunctions::setupSDFileList(bool update) {
- sd_obj.sd_files->clear();
-
- delete sd_obj.sd_files;
-
- sd_obj.sd_files = new LinkedList();
-
- if (!update)
- sd_obj.listDirToLinkedList(sd_obj.sd_files);
- else
- sd_obj.listDirToLinkedList(sd_obj.sd_files, "/", ".bin");
-}
-
-void MenuFunctions::buildSDFileMenu(bool update) {
- this->setupSDFileList(update);
-
- sdDeleteMenu.list->clear();
- delete sdDeleteMenu.list;
- sdDeleteMenu.list = new LinkedList();
-
- if (!update)
- sdDeleteMenu.name = "SD Files";
- else
- sdDeleteMenu.name = "Bin Files";
-
- this->addNodes(&sdDeleteMenu, text09, TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(sdDeleteMenu.parentMenu, true);
- });
-
- if (!update) {
- this->addNodes(&sdDeleteMenu, "Delete Selected", TFTORANGE, 0, [this]() {
- for (int x = 0; x < sd_obj.sd_files->size(); x++) {
- if (current_menu->list->get(x + 2).selected) {
- if (sd_obj.removeFile("/" + sd_obj.sd_files->get(x))) {
- Serial.println("Deleted /" + sd_obj.sd_files->get(x));
- display_obj.clearScreen();
- display_obj.tft.setTextWrap(false);
- display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
- display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
- display_obj.tft.println("Deleting /" + sd_obj.sd_files->get(x) + "...");
- }
- }
- }
- this->buildSDFileMenu();
- this->changeMenu(&sdDeleteMenu, true);
- });
- }
-
- if (!update) {
- for (int x = 0; x < sd_obj.sd_files->size(); x++) {
- this->addNodes(&sdDeleteMenu, sd_obj.sd_files->get(x).c_str(), TFTCYAN, SD_UPDATE, [this, x]() {
- // Change selection status of menu node
- MenuNode new_node = current_menu->list->get(x + 2);
- new_node.selected = !current_menu->list->get(x + 2).selected;
- current_menu->list->set(x + 2, new_node);
- });
- }
- }
- else {
- for (int x = 0; x < sd_obj.sd_files->size(); x++) {
- this->addNodes(&sdDeleteMenu, sd_obj.sd_files->get(x).c_str(), TFTCYAN, SD_UPDATE, [this, x]() {
- wifi_scan_obj.currentScanMode = OTA_UPDATE;
- this->changeMenu(&failedUpdateMenu, true);
- sd_obj.runUpdate("/" + sd_obj.sd_files->get(x));
- });
- }
- }
-}
-
-
-// Function to add MenuNodes to a menu
-void MenuFunctions::addNodes(Menu * menu, const char* name, uint8_t color, int place, std::function callable, bool selected)
-{
- //Serial.println("Building node: " + name);
- menu->list->add(MenuNode{String(name), false, color, place, selected, callable});
-}
-
-void MenuFunctions::setGraphScale(float scale) {
- this->_graph_scale = scale;
-}
-
-float MenuFunctions::calculateGraphScale(uint8_t value) {
- if ((value * this->_graph_scale < GRAPH_VERT_LIM) && (value * this->_graph_scale > GRAPH_VERT_LIM * 0.75)) {
- return this->_graph_scale; // No scaling needed if the value is within the limit
- }
-
- if (value < GRAPH_VERT_LIM)
- return 1.0;
-
- // Calculate the multiplier proportionally
- return (0.75 * GRAPH_VERT_LIM) / value;
-}
-
-float MenuFunctions::calculateGraphScale(int16_t value) {
- if ((value * this->_graph_scale < GRAPH_VERT_LIM) && (value * this->_graph_scale > GRAPH_VERT_LIM * 0.75)) {
- return this->_graph_scale; // No scaling needed if the value is within the limit
- }
-
- if (value < GRAPH_VERT_LIM)
- return 1.0;
-
- // Calculate the multiplier proportionally
- return (0.75 * GRAPH_VERT_LIM) / value;
-}
-
-float MenuFunctions::graphScaleCheck(const int16_t array[SCREEN_WIDTH]) {
- int16_t maxValue = 0;
-
- // Iterate through the array to find the highest value
- for (int16_t i = 0; i < SCREEN_WIDTH; i++) {
- if (array[i] > maxValue) {
- maxValue = array[i];
- }
- }
-
- // If the highest value exceeds GRAPH_VERT_LIM, call calculateMultiplier
- if (maxValue > GRAPH_VERT_LIM) {
- return this->calculateGraphScale(maxValue);
- }
-
- // If the highest value does not exceed GRAPH_VERT_LIM, return 1.0
- return 1.0;
-}
-
-float MenuFunctions::graphScaleCheckSmall(const uint8_t array[CHAN_PER_PAGE]) {
- uint8_t maxValue = 0;
-
- // Iterate through the array to find the highest value
- for (uint8_t i = 0; i < CHAN_PER_PAGE; i++) {
- if (array[i] > maxValue) {
- maxValue = array[i];
- }
- }
-
- // If the highest value exceeds GRAPH_VERT_LIM, call calculateMultiplier
- if (maxValue > GRAPH_VERT_LIM) {
- return this->calculateGraphScale(maxValue);
- }
-
- // If the highest value does not exceed GRAPH_VERT_LIM, return 1.0
- return 1.0;
-}
-
-void MenuFunctions::drawMaxLine(int16_t value, uint16_t color) {
- display_obj.tft.drawLine(0, TFT_HEIGHT - (value * this->_graph_scale), TFT_WIDTH, TFT_HEIGHT - (value * this->_graph_scale), color);
- display_obj.tft.setCursor(0, TFT_HEIGHT - (value * this->_graph_scale));
- display_obj.tft.setTextColor(color, TFT_BLACK);
- display_obj.tft.setTextSize(1);
- display_obj.tft.println((String)(value / BASE_MULTIPLIER));
-}
-
-void MenuFunctions::drawMaxLine(uint8_t value, uint16_t color) {
- //display_obj.tft.drawLine(0, TFT_HEIGHT - (value * this->_graph_scale), TFT_WIDTH, TFT_HEIGHT - (value * this->_graph_scale), color);
- display_obj.tft.setCursor(0, TFT_HEIGHT - (value * this->_graph_scale));
- display_obj.tft.setTextColor(color, TFT_BLACK);
- display_obj.tft.setTextSize(1);
- display_obj.tft.println((String)value);
-}
-
-void MenuFunctions::drawGraphSmall(uint8_t *values) {
- uint8_t maxValue = 0;
- //(i + (CHAN_PER_PAGE * (this->activity_page - 1)))
-
- int bar_width = SCREEN_WIDTH / (CHAN_PER_PAGE * 2);
- //display_obj.tft.fillRect(0, TFT_HEIGHT / 2 + 1, SCREEN_WIDTH, (TFT_HEIGHT / 2) + 1, TFT_BLACK);
-
- #ifndef HAS_DUAL_BAND
- for (int i = 1; i < CHAN_PER_PAGE + 1; i++) {
- int targ_val = i + (CHAN_PER_PAGE * (wifi_scan_obj.activity_page - 1)) - 1;
- int x_mult = (i * 2) - 1;
- int x_coord = (SCREEN_WIDTH / (CHAN_PER_PAGE * 2)) * (x_mult - 1);
-
- if (values[targ_val] > maxValue) {
- maxValue = values[targ_val];
- }
-
- if (values[targ_val] * this->_graph_scale <= GRAPH_VERT_LIM) {
- display_obj.tft.fillRect(x_coord, SCREEN_HEIGHT / 2 + 1, bar_width, SCREEN_HEIGHT / 2 + 1, TFT_BLACK);
- display_obj.tft.fillRect(x_coord, SCREEN_HEIGHT - (values[targ_val] * this->_graph_scale), bar_width, values[targ_val] * this->_graph_scale, TFT_CYAN);
- }
-
- display_obj.tft.drawLine(x_coord - 2, SCREEN_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 2), x_coord - 2, SCREEN_HEIGHT, TFT_WHITE);
- }
- #else
- for (int i = 1; i < CHAN_PER_PAGE + 1; i++) {
- int targ_val = i + (CHAN_PER_PAGE * (wifi_scan_obj.activity_page - 1)) - 1;
- int x_mult = (i * 2) - 1;
- int x_coord = (SCREEN_WIDTH / (CHAN_PER_PAGE * 2)) * (x_mult - 1);
-
- if (values[targ_val] > maxValue) {
- maxValue = values[targ_val];
- }
-
- if (values[targ_val] * this->_graph_scale <= GRAPH_VERT_LIM) {
- display_obj.tft.fillRect(x_coord, SCREEN_HEIGHT / 2 + 1, bar_width + 3, SCREEN_HEIGHT / 2 + 1, TFT_BLACK);
- display_obj.tft.fillRect(x_coord, SCREEN_HEIGHT - (values[targ_val] * this->_graph_scale), bar_width, values[targ_val] * this->_graph_scale, TFT_CYAN);
- }
-
- display_obj.tft.drawLine(x_coord - 2, SCREEN_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 2), x_coord - 2, SCREEN_HEIGHT, TFT_WHITE);
- }
- #endif
-
- this->drawMaxLine(maxValue, TFT_GREEN); // Draw max
-}
-
-void MenuFunctions::drawGraph(int16_t *values) {
- #if !defined(MARAUDER_CARDPUTER) && !defined(MARAUDER_CARDPUTER_ADV)
- int width = TFT_WIDTH;
- #else
- int width = SCREEN_WIDTH;
- #endif
-
- int16_t maxValue = 0;
- int total = 0;
- for (int i = width - 1; i >= 0; i--) {
- if (values[i] >= 0) {
- total = total + values[i];
- if (values[i] > maxValue) {
- maxValue = values[i];
- }
- #if !defined(MARAUDER_CARDPUTER) && !defined(MARAUDER_CARDPUTER_ADV)
- display_obj.tft.drawLine(i, TFT_HEIGHT, i, TFT_HEIGHT - GRAPH_VERT_LIM, TFT_BLACK);
- display_obj.tft.drawLine(i, TFT_HEIGHT, i, TFT_HEIGHT - (values[i] * this->_graph_scale), TFT_CYAN);
- #else
- display_obj.tft.drawLine(i, TFT_WIDTH, i, TFT_WIDTH - GRAPH_VERT_LIM, TFT_BLACK);
- display_obj.tft.drawLine(i, TFT_WIDTH, i, TFT_WIDTH - (values[i] * this->_graph_scale), TFT_CYAN);
- display_obj.tft.setCursor(0, 0);
- display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK);
- #endif
- }
- else {
- int16_t ch_val = values[i] * -1;
- #if !defined(MARAUDER_CARDPUTER) && !defined(MARAUDER_CARDPUTER_ADV)
- display_obj.tft.drawLine(i, TFT_HEIGHT, i, TFT_HEIGHT - GRAPH_VERT_LIM, TFT_BLACK);
- display_obj.tft.drawLine(i, TFT_HEIGHT, i, TFT_HEIGHT - GRAPH_VERT_LIM, TFT_RED);
- display_obj.tft.setCursor(i, TFT_HEIGHT - GRAPH_VERT_LIM);
- #else
- display_obj.tft.drawLine(i, TFT_WIDTH, i, TFT_WIDTH - GRAPH_VERT_LIM, TFT_BLACK);
- display_obj.tft.drawLine(i, TFT_WIDTH, i, TFT_WIDTH - GRAPH_VERT_LIM, TFT_RED);
- display_obj.tft.setCursor(i, TFT_WIDTH - GRAPH_VERT_LIM);
- #endif
- display_obj.tft.setTextColor(TFT_BLACK, TFT_RED);
- display_obj.tft.setTextSize(1);
- display_obj.tft.println((String)ch_val);
- }
- }
-
- this->drawMaxLine(maxValue, TFT_GREEN); // Draw max
- this->drawMaxLine((int16_t)(total / TFT_WIDTH), TFT_ORANGE); // Draw average
-}
-
-void MenuFunctions::renderGraphUI(uint8_t scan_mode) {
- display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK);
- if (scan_mode == WIFI_SCAN_CHAN_ANALYZER)
- display_obj.tft.drawCentreString("Frames/" + (String)BANNER_TIME + "ms", SCREEN_WIDTH / 2, SCREEN_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 2), 1);
- else if (scan_mode == BT_SCAN_ANALYZER)
- display_obj.tft.drawCentreString("BLE Beacons/" + (String)BANNER_TIME + "ms", SCREEN_WIDTH / 2, SCREEN_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 2), 1);
- display_obj.tft.drawLine(0, SCREEN_HEIGHT - GRAPH_VERT_LIM - 1, SCREEN_WIDTH, SCREEN_HEIGHT - GRAPH_VERT_LIM - 1, TFT_WHITE);
- display_obj.tft.setCursor(0, SCREEN_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 8));
- display_obj.tft.setTextSize(1);
- display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK);
- display_obj.tft.println("Max");
- display_obj.tft.setTextColor(TFT_ORANGE, TFT_BLACK);
- display_obj.tft.println("Average");
- display_obj.tft.setTextColor(TFT_RED, TFT_BLACK);
- if (scan_mode != BT_SCAN_ANALYZER)
- display_obj.tft.println("Channel Marker");
-}
-
-uint16_t MenuFunctions::getColor(uint16_t color) {
- if (color == TFTWHITE) return TFT_WHITE;
- else if (color == TFTCYAN) return TFT_CYAN;
- else if (color == TFTBLUE) return TFT_BLUE;
- else if (color == TFTRED) return TFT_RED;
- else if (color == TFTGREEN) return TFT_GREEN;
- else if (color == TFTGREY) return TFT_LIGHTGREY;
- else if (color == TFTGRAY) return TFT_LIGHTGREY;
- else if (color == TFTMAGENTA) return TFT_MAGENTA;
- else if (color == TFTVIOLET) return TFT_VIOLET;
- else if (color == TFTORANGE) return TFT_ORANGE;
- else if (color == TFTYELLOW) return TFT_YELLOW;
- else if (color == TFTLIGHTGREY) return TFT_LIGHTGREY;
- else if (color == TFTPURPLE) return TFT_PURPLE;
- else if (color == TFTNAVY) return TFT_NAVY;
- else if (color == TFTSILVER) return TFT_SILVER;
- else if (color == TFTDARKGREY) return TFT_DARKGREY;
- else if (color == TFTSKYBLUE) return TFT_SKYBLUE;
- else if (color == TFTLIME) return 0x97e0;
- else return color;
-}
-
-// Function to change menu
-void MenuFunctions::changeMenu(Menu* menu, bool simple_change) {
- if (!simple_change) {
- //display_obj.initScrollValues();
- //display_obj.setupScrollArea(TOP_FIXED_AREA, BOT_FIXED_AREA);
- display_obj.init();
-
- #ifdef HAS_ILI9341
- extern void backlightOn();
- backlightOn();
- #endif
- }
- current_menu = menu;
-
- current_menu->selected = 0;
-
- buildButtons(menu);
-
- displayCurrentMenu();
-
- //#ifdef MARAUDER_V8
- // digitalWrite(TFT_BL, HIGH);
- //#endif
-}
-
-void MenuFunctions::buildButtons(Menu *menu, int starting_index, const char* button_name) {
- if (menu->list == NULL || menu->list->size() == 0)
- return;
-
- if (starting_index >= menu->list->size())
- starting_index = menu->list->size() - BUTTON_SCREEN_LIMIT;
- if (starting_index < 0)
- starting_index = 0;
-
- this->menu_start_index = starting_index;
-
- uint8_t visible_buttons = min(BUTTON_SCREEN_LIMIT, menu->list->size() - starting_index);
-
- for (uint8_t i = 0; i < visible_buttons; i++) {
- MenuNode node = menu->list->get(starting_index + i);
- uint16_t color = (node.icon == SETTINGS && node.color == TFTLIGHTGREY) ? (node.selected ? TFT_GREEN : TFT_RED) : this->getColor(node.color);
-
- char buf[64];
-
- if (button_name != nullptr && button_name[0] != '\0') {
- strncpy(buf, button_name, sizeof(buf));
- buf[sizeof(buf) - 1] = '\0';
- } else {
- node.name.toCharArray(buf, sizeof(buf));
- }
-
- display_obj.key[i].initButton(&display_obj.tft,
- KEY_X,
- KEY_Y + i * (KEY_H + KEY_SPACING_Y),
- KEY_W,
- KEY_H,
- TFT_BLACK,
- TFT_BLACK,
- color,
- buf,
- KEY_TEXTSIZE);
-
- #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
- display_obj.key[i].setLabelDatum(BUTTON_PADDING - (KEY_W / 2), 4, ML_DATUM);
- #else
- display_obj.key[i].setLabelDatum(BUTTON_PADDING - (KEY_W / 2), 2, ML_DATUM);
- #endif
- }
-
- for (int i = BUTTON_ARRAY_LEN; i < BUTTON_ARRAY_LEN + 3; i++) {
- uint16_t x = TFT_WIDTH / 2;
- uint16_t y = TFT_HEIGHT / 3 * (i - BUTTON_ARRAY_LEN) + ((TFT_HEIGHT / 3) / 2);
- uint16_t w = TFT_WIDTH;
- uint16_t h = TFT_HEIGHT / 3 - 1;
-
- display_obj.key[i].initButton(&display_obj.tft,
- x,
- y,
- w,
- h,
- TFT_LIGHTGREY,
- TFT_BLACK,
- TFT_BLACK,
- "Chicken",
- 1);
- }
-}
-
-void MenuFunctions::displayCurrentMenu(int start_index)
-{
- //Serial.println(F("Displaying current menu..."));
- display_obj.clearScreen();
- display_obj.updateBanner(current_menu->name);
- display_obj.tft.setTextColor(TFT_LIGHTGREY, TFT_DARKGREY);
- this->drawStatusBar();
-
- if (current_menu->list != NULL)
- {
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.setFreeFont(MENU_FONT);
- #endif
-
- #ifdef HAS_MINI_SCREEN
- display_obj.tft.setFreeFont(NULL);
- display_obj.tft.setTextSize(1);
- #endif
-
- for (uint16_t i = start_index; i < min(start_index + BUTTON_SCREEN_LIMIT, current_menu->list->size()); i++)
- {
- if (!current_menu || !current_menu->list || i >= current_menu->list->size())
- continue;
- uint16_t color = this->getColor(current_menu->list->get(i).color);
- #ifdef HAS_FULL_SCREEN
- bool is_setting_node = (current_menu->list->get(i).icon == SETTINGS && current_menu->list->get(i).color == TFTLIGHTGREY);
- if (is_setting_node && current_menu->selected == i) {
- uint16_t setting_color = current_menu->list->get(i).selected ? TFT_GREEN : TFT_RED;
- display_obj.key[i - start_index].initButton(&display_obj.tft, KEY_X, KEY_Y + (i - start_index) * (KEY_H + KEY_SPACING_Y), KEY_W, KEY_H, TFT_BLACK, TFT_LIGHTGREY, setting_color, (char*)"", KEY_TEXTSIZE);
- display_obj.key[i - start_index].drawButton(false, current_menu->list->get(i).name);
- display_obj.tft.drawXBitmap(0,
- KEY_Y + (i - start_index) * (KEY_H + KEY_SPACING_Y) - (ICON_H / 2),
- menu_icons[current_menu->list->get(i).icon],
- ICON_W,
- ICON_H,
- TFT_BLACK,
- TFT_LIGHTGREY);
- } else if ((!is_setting_node && current_menu->list->get(i).selected) || (current_menu->selected == i)) {
- display_obj.key[i - start_index].drawButton(true, current_menu->list->get(i).name);
- if ((current_menu->list->get(i).name != text09) && (current_menu->list->get(i).icon != 255))
- display_obj.tft.drawXBitmap(0,
- KEY_Y + (i - start_index) * (KEY_H + KEY_SPACING_Y) - (ICON_H / 2),
- menu_icons[current_menu->list->get(i).icon],
- ICON_W,
- ICON_H,
- TFT_BLACK,
- color);
- } else {
- display_obj.key[i - start_index].drawButton(false, current_menu->list->get(i).name);
- if ((current_menu->list->get(i).name != text09) && (current_menu->list->get(i).icon != 255))
- display_obj.tft.drawXBitmap(0,
- KEY_Y + (i - start_index) * (KEY_H + KEY_SPACING_Y) - (ICON_H / 2),
- menu_icons[current_menu->list->get(i).icon],
- ICON_W,
- ICON_H,
- TFT_BLACK,
- is_setting_node ? TFT_LIGHTGREY : color);
- }
-
- #endif
-
- #ifdef HAS_MINI_SCREEN
- if ((current_menu->selected == i) || ((current_menu->list->get(i).icon != SETTINGS || current_menu->list->get(i).color != TFTLIGHTGREY) && current_menu->list->get(i).selected))
- this->drawMiniMenuButton(i - start_index, i, true);
- else
- this->drawMiniMenuButton(i - start_index, i, false);
- #endif
- }
- display_obj.tft.setFreeFont(NULL);
- }
-
- this->displayMenuButtons();
-}
-
-// ============================================================
-// BRIGHTNESS ADJUSTMENT MODE
-// Hold top/bottom zone 1.5s to enter. TAP TOP = brighter, TAP BOTTOM = dimmer.
-// TAP MIDDLE or wait 3s = save & exit.
-// ============================================================
-#ifndef HAS_MINI_SCREEN
- void MenuFunctions::brightnessMode() {
- extern void brightnessSave(uint8_t level);
- extern uint8_t getBrightnessLevel();
-
- const uint8_t levels[] = {26, 51, 77, 102, 128, 153, 179, 204, 230, 255};
- const uint8_t numLevels = 10;
- uint8_t level = getBrightnessLevel();
-
- // LEDC write compatibility (2.x vs 3.x board package)
- #if ESP_ARDUINO_VERSION_MAJOR >= 3
- #define BL_PREVIEW(duty) ledcWrite(TFT_BL, (duty))
- #else
- #define BL_PREVIEW(duty) ledcWrite(0, (duty))
- #endif
-
- display_obj.tft.fillScreen(TFT_BLACK);
- display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
- display_obj.tft.drawCentreString("BRIGHTNESS", TFT_WIDTH/2, 30, 2);
-
- display_obj.tft.setTextColor(TFT_DARKGREY, TFT_BLACK);
- display_obj.tft.drawCentreString("TAP TOP = BRIGHTER", TFT_WIDTH/2, 10, 1);
- display_obj.tft.drawCentreString("TAP BOTTOM = DIMMER", TFT_WIDTH/2, TFT_HEIGHT - 20, 1);
- display_obj.tft.setTextColor(TFT_RED, TFT_BLACK);
- display_obj.tft.drawCentreString("TAP MIDDLE or WAIT 3s = SAVE", TFT_WIDTH/2, TFT_HEIGHT/2 + 50, 1);
-
- auto drawBar = [&]() {
- uint16_t barX = 30, barY = TFT_HEIGHT/2 - 25, barW = TFT_WIDTH - 60, barH = 30;
- display_obj.tft.drawRect(barX, barY, barW, barH, TFT_WHITE);
- uint16_t fillW = (barW - 4) * (level + 1) / numLevels;
- display_obj.tft.fillRect(barX + 2, barY + 2, barW - 4, barH - 4, TFT_BLACK);
- display_obj.tft.fillRect(barX + 2, barY + 2, fillW, barH - 4, TFT_CYAN);
- display_obj.tft.fillRect(0, barY + barH + 5, TFT_WIDTH, 20, TFT_BLACK);
- display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK);
- String pct = String(levels[level] * 100 / 255) + "%";
- display_obj.tft.drawCentreString(pct, TFT_WIDTH/2, barY + barH + 8, 2);
- };
- drawBar();
-
- uint16_t zoneUp = TFT_HEIGHT * 25 / 100;
- uint16_t zoneDown = TFT_HEIGHT * 75 / 100;
- uint32_t lastTouch = millis();
-
- while (true) {
- // Auto-save after 3s of no touch
- if (millis() - lastTouch >= 3000) {
- brightnessSave(level);
- break;
- }
-
- uint16_t tx, ty;
- if (display_obj.updateTouch(&tx, &ty)) {
- lastTouch = millis();
- // Wait for release
- while (display_obj.updateTouch(&tx, &ty)) delay(10);
-
- if (ty < zoneUp) {
- if (level < numLevels - 1) {
- level++;
- BL_PREVIEW(levels[level]);
- drawBar();
- }
- } else if (ty >= zoneDown) {
- if (level > 0) {
- level--;
- BL_PREVIEW(levels[level]);
- drawBar();
- }
- } else {
- // Middle = save now
- brightnessSave(level);
- break;
- }
- delay(150);
- }
- delay(30);
- }
-
- #undef BL_PREVIEW
- this->changeMenu(current_menu, true);
- }
-#endif
-
-#endif
-
-
-
+
+ // Bluetooth Attack menu
+ bluetoothAttackMenu.parentMenu = &bluetoothMenu; // Second Menu is third menu parent
+ this->addNodes(&bluetoothAttackMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(bluetoothAttackMenu.parentMenu, true);
+ });
+ this->addNodes(&bluetoothAttackMenu, "Sour Apple", TFTGREEN, DEAUTH_SNIFF, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(BT_ATTACK_SOUR_APPLE, TFT_GREEN);
+ });
+ this->addNodes(&bluetoothAttackMenu, "Apple Juice", TFTYELLOW, DEAUTH_SNIFF, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(BT_ATTACK_APPLE_JUICE, TFT_YELLOW);
+ });
+ this->addNodes(&bluetoothAttackMenu, "Swiftpair Spam", TFTCYAN, KEYBOARD_ICO, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(BT_ATTACK_SWIFTPAIR_SPAM, TFT_CYAN);
+ });
+ this->addNodes(&bluetoothAttackMenu, "Samsung BLE Spam", TFTRED, GENERAL_APPS, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(BT_ATTACK_SAMSUNG_SPAM, TFT_RED);
+ });
+ this->addNodes(&bluetoothAttackMenu, "Google BLE Spam", TFTPURPLE, LANGUAGE, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(BT_ATTACK_GOOGLE_SPAM, TFT_PURPLE);
+ });
+ this->addNodes(&bluetoothAttackMenu, "Flipper BLE Spam", TFTORANGE, FLIPPER, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(BT_ATTACK_FLIPPER_SPAM, TFT_ORANGE);
+ });
+ this->addNodes(&bluetoothAttackMenu, "BLE Spam All", TFTMAGENTA, DEAUTH_SNIFF, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(BT_ATTACK_SPAM_ALL, TFT_MAGENTA);
+ });
+
+#endif
+
+ //#ifndef HAS_ILI9341
+ #ifdef HAS_BT
+ this->addNodes(&bluetoothAttackMenu, "Spoof Airtag", TFTWHITE, ATTACKS, [this](){
+ wifiAPMenu.parentMenu = &bluetoothAttackMenu;
+
+ // Clear nodes and add back button
+ wifiAPMenu.list->clear();
+ this->addNodes(&wifiAPMenu, text09, TFT_LIGHTGREY, 0, [this]() {
+ this->changeMenu(wifiAPMenu.parentMenu, true);
+ });
+
+ // Add buttons for all airtags
+ // Find out how big our menu is going to be
+ int menu_limit;
+ if (airtags->size() <= BUTTON_ARRAY_LEN)
+ menu_limit = airtags->size();
+ else
+ menu_limit = BUTTON_ARRAY_LEN;
+
+ // Create the menu nodes for all of the list items
+ for (int i = 0; i < menu_limit; i++) {
+ this->addNodes(&wifiAPMenu, airtags->get(i).mac.c_str(), TFTWHITE, BLUETOOTH, [this, i](){
+ AirTag new_at = airtags->get(i);
+ new_at.selected = true;
+
+ airtags->set(i, new_at);
+
+ // Set all other airtags to "Not Selected"
+ for (int x = 0; x < airtags->size(); x++) {
+ if (x != i) {
+ AirTag new_atx = airtags->get(x);
+ new_atx.selected = false;
+ airtags->set(x, new_atx);
+ }
+ }
+
+ // Start the spoof
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(BT_SPOOF_AIRTAG, TFT_WHITE);
+
+ });
+ }
+ this->changeMenu(&wifiAPMenu, true);
+ });
+
+ #ifdef HAS_NIMBLE_2
+ this->addNodes(&bluetoothAttackMenu, "FindMy Sound", TFTCYAN, ATTACKS, [this](){
+ wifiAPMenu.parentMenu = &bluetoothAttackMenu;
+
+ // Clear nodes and add back button
+ wifiAPMenu.list->clear();
+ this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(wifiAPMenu.parentMenu, true);
+ });
+
+ /*this->addNodes(&wifiAPMenu, "Live", TFTMAGENTA, 0, [this]() {
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.StartScan(BT_ATTACK_FINDMY_LIVE, TFT_RED);
+ });*/
+
+ int menu_limit = airtags->size();
+
+ // Create the menu nodes for all of the list items
+ for (int i = 0; i < menu_limit; i++) {
+ uint8_t node_color = rssiToMenuColor(airtags->get(i).rssi);
+ String node_name = String(airtags->get(i).rssi) + " " + airtags->get(i).mac;
+ this->addNodes(&wifiAPMenu, node_name.c_str(), node_color, BLUETOOTH, [this, i](){
+ AirTag new_at = airtags->get(i);
+ new_at.selected = true;
+ new_at.connectable = true;
+
+ airtags->set(i, new_at);
+
+ // Set all other airtags to "Not Selected"
+ for (int x = 0; x < airtags->size(); x++) {
+ if (x != i) {
+ AirTag new_atx = airtags->get(x);
+ new_atx.selected = false;
+ airtags->set(x, new_atx);
+ }
+ }
+
+ // Start the spoof
+ display_obj.clearScreen();
+ this->drawStatusBar();
+ wifi_scan_obj.executeFindMySound(true);
+ delay(2000);
+ this->changeMenu(&wifiAPMenu, true);
+ });
+ }
+ this->changeMenu(&wifiAPMenu, true);
+ });
+ #endif
+
+ wifiAPMenu.parentMenu = &bluetoothAttackMenu;
+ this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(wifiAPMenu.parentMenu, true);
+ });
+
+ wifiAPMenu.parentMenu = &bluetoothAttackMenu;
+ this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(wifiAPMenu.parentMenu, true);
+ });
+ #endif
+
+ //#endif
+
+ // Device menu
+ deviceMenu.parentMenu = &mainMenu;
+ this->addNodes(&deviceMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(deviceMenu.parentMenu, true);
+ });
+
+ #ifdef HAS_SD
+ if (sd_obj.supported) {
+
+ sdDeleteMenu.parentMenu = &deviceMenu;
+
+ this->addNodes(&deviceMenu, "Update Firmware", TFTORANGE, SD_UPDATE, [this]() {
+ display_obj.clearScreen();
+ display_obj.tft.setTextWrap(false);
+ display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
+ display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
+ display_obj.tft.println("Loading...");
+
+ // Clear menu and lists
+ this->buildSDFileMenu(true);
+
+ this->changeMenu(&sdDeleteMenu, true);
+ });
+ }
+ #endif
+
+ this->addNodes(&deviceMenu, "Save/Load Files", TFTCYAN, SD_UPDATE, [this]() {
+ this->changeMenu(&saveFileMenu, true);
+ });
+
+ #ifndef HAS_MINI_SCREEN
+ this->addNodes(&deviceMenu, "Brightness", TFTYELLOW, BRIGHTNESS, [this]() {
+ this->brightnessMode();
+ });
+ #endif
+
+ this->addNodes(&deviceMenu, text_table1[17], TFTWHITE, DEVICE_INFO, [this]() {
+ wifi_scan_obj.currentScanMode = SHOW_INFO;
+ this->changeMenu(&infoMenu, true);
+ wifi_scan_obj.RunInfo();
+ });
+ this->addNodes(&deviceMenu, text08, TFTBLUE, SETTINGS, [this]() {
+ this->changeMenu(&settingsMenu, true);
+ });
+
+ #ifdef HAS_SD
+ if (sd_obj.supported) {
+
+ sdDeleteMenu.parentMenu = &deviceMenu;
+
+ this->addNodes(&deviceMenu, "Delete SD Files", TFTCYAN, SD_UPDATE, [this]() {
+ display_obj.clearScreen();
+ display_obj.tft.setTextWrap(false);
+ display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
+ display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
+ display_obj.tft.println("Loading...");
+
+ // Clear menu and lists
+ this->buildSDFileMenu();
+
+ this->changeMenu(&sdDeleteMenu, true);
+ });
+ }
+ #endif
+
+ // Save Files Menu
+ saveFileMenu.parentMenu = &deviceMenu;
+ this->addNodes(&saveFileMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(saveFileMenu.parentMenu, true);
+ });
+ this->addNodes(&saveFileMenu, "Save SSIDs", TFTCYAN, SD_UPDATE, [this]() {
+ this->changeMenu(&saveSSIDsMenu, true);
+ wifi_scan_obj.RunSaveSSIDList(true);
+ });
+ this->addNodes(&saveFileMenu, "Load SSIDs", TFTSKYBLUE, SD_UPDATE, [this]() {
+ this->changeMenu(&loadSSIDsMenu, true);
+ wifi_scan_obj.RunLoadSSIDList();
+ });
+ this->addNodes(&saveFileMenu, "Save APs", TFTNAVY, SD_UPDATE, [this]() {
+ this->changeMenu(&saveAPsMenu, true);
+ wifi_scan_obj.RunSaveAPList();
+ });
+ this->addNodes(&saveFileMenu, "Load APs", TFTBLUE, SD_UPDATE, [this]() {
+ this->changeMenu(&loadAPsMenu, true);
+ wifi_scan_obj.RunLoadAPList();
+ });
+ this->addNodes(&saveFileMenu, "Save Airtags", TFTWHITE, SD_UPDATE, [this]() {
+ this->changeMenu(&saveAPsMenu, true);
+ wifi_scan_obj.RunSaveATList();
+ });
+ this->addNodes(&saveFileMenu, "Load Airtags", TFTWHITE, SD_UPDATE, [this]() {
+ this->changeMenu(&loadAPsMenu, true);
+ wifi_scan_obj.RunLoadATList();
+ });
+
+ saveSSIDsMenu.parentMenu = &saveFileMenu;
+ this->addNodes(&saveSSIDsMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(saveSSIDsMenu.parentMenu, true);
+ });
+
+ loadSSIDsMenu.parentMenu = &saveFileMenu;
+ this->addNodes(&loadSSIDsMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(loadSSIDsMenu.parentMenu, true);
+ });
+
+ saveAPsMenu.parentMenu = &saveFileMenu;
+ this->addNodes(&saveAPsMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(saveAPsMenu.parentMenu, true);
+ });
+
+ loadAPsMenu.parentMenu = &saveFileMenu;
+ this->addNodes(&loadAPsMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(loadAPsMenu.parentMenu, true);
+ });
+
+ saveATsMenu.parentMenu = &saveFileMenu;
+ this->addNodes(&saveATsMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(saveATsMenu.parentMenu, true);
+ });
+
+ loadATsMenu.parentMenu = &saveFileMenu;
+ this->addNodes(&loadATsMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(loadATsMenu.parentMenu, true);
+ });
+
+ // GPS Menu
+ #ifdef HAS_GPS
+ if (gps_obj.getGpsModuleStatus()) {
+ gpsMenu.parentMenu = &mainMenu; // Main Menu is second menu parent
+
+ this->addNodes(&gpsMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(gpsMenu.parentMenu, true);
+ });
+
+ this->addNodes(&gpsMenu, "GPS Data", TFTRED, GPS_MENU, [this]() {
+ wifi_scan_obj.currentScanMode = WIFI_SCAN_GPS_DATA;
+ this->changeMenu(&gpsInfoMenu, true);
+ wifi_scan_obj.StartScan(WIFI_SCAN_GPS_DATA, TFT_CYAN);
+ });
+
+ this->addNodes(&gpsMenu, "NMEA Stream", TFTORANGE, GPS_MENU, [this]() {
+ wifi_scan_obj.currentScanMode = WIFI_SCAN_GPS_NMEA;
+ this->changeMenu(&gpsInfoMenu, true);
+ wifi_scan_obj.StartScan(WIFI_SCAN_GPS_NMEA, TFT_ORANGE);
+ });
+
+ this->addNodes(&gpsMenu, "GPS Tracker", TFTGREEN, GPS_MENU, [this]() {
+ wifi_scan_obj.currentScanMode = GPS_TRACKER;
+ this->changeMenu(&gpsInfoMenu, true);
+ wifi_scan_obj.StartScan(GPS_TRACKER, TFT_CYAN);
+ });
+
+ this->addNodes(&gpsMenu, "GPS POI", TFTCYAN, GPS_MENU, [this]() {
+ wifi_scan_obj.StartScan(GPS_POI, TFT_CYAN);
+ wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF;
+ this->changeMenu(&gpsPOIMenu, true);
+ });
+
+ // GPS POI Menu
+ gpsPOIMenu.parentMenu = &gpsMenu;
+ this->addNodes(&gpsPOIMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ wifi_scan_obj.currentScanMode = GPS_POI;
+ wifi_scan_obj.StartScan(WIFI_SCAN_OFF);
+ this->changeMenu(gpsPOIMenu.parentMenu, true);
+ });
+ this->addNodes(&gpsPOIMenu, "Mark POI", TFTCYAN, GPS_MENU, [this]() {
+ wifi_scan_obj.currentScanMode = GPS_POI;
+ display_obj.tft.setCursor(0, TFT_HEIGHT / 2);
+ display_obj.clearScreen();
+ if (wifi_scan_obj.RunGPSInfo(true, false, true))
+ display_obj.showCenterText("POI Logged", TFT_HEIGHT / 2);
+ else
+ display_obj.showCenterText("POI Log Failed", TFT_HEIGHT / 2);
+ wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF;
+ delay(2000);
+ this->changeMenu(&gpsPOIMenu, true);
+ });
+
+ // GPS Info Menu
+ gpsInfoMenu.parentMenu = &gpsMenu;
+ this->addNodes(&gpsInfoMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ if(wifi_scan_obj.currentScanMode != GPS_TRACKER)
+ wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF;
+ wifi_scan_obj.StartScan(WIFI_SCAN_OFF);
+ this->changeMenu(gpsInfoMenu.parentMenu, true);
+ });
+ }
+ #endif
+
+ // Settings menu
+ // Device menu
+ settingsMenu.parentMenu = &deviceMenu;
+ this->addNodes(&settingsMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ changeMenu(settingsMenu.parentMenu, true);
+ });
+ for (int i = 0; i < settings_obj.getNumberSettings(); i++) {
+ String settingName = settings_obj.setting_index_to_name(i);
+ const char* type = this->callSetting(settingName.c_str());
+ if (type && strcmp(type, "bool") == 0) {
+ this->addNodes(&settingsMenu, settingName.c_str(), TFTLIGHTGREY, SETTINGS, [this, i, settingName]() {
+ settings_obj.toggleSetting(settingName.c_str());
+ this->callSetting(settingName.c_str());
+ this->changeMenu(&specSettingMenu, true);
+ this->displaySetting(settingName.c_str(), &settingsMenu, i + 1);
+ wifi_scan_obj.force_pmkid = settings_obj.loadSetting(text_table4[5]);
+ wifi_scan_obj.force_probe = settings_obj.loadSetting(text_table4[6]);
+ wifi_scan_obj.save_pcap = settings_obj.loadSetting(text_table4[7]);
+ wifi_scan_obj.ep_deauth = settings_obj.loadSetting("EPDeauth");
+ wifi_scan_obj.channel_hop = settings_obj.loadSetting("ChanHop");
+ }, settings_obj.loadSetting(settingName.c_str()));
+ }
+ }
+
+ Serial.println("Finished settings nodes");
+
+ // Specific setting menu
+ specSettingMenu.parentMenu = &settingsMenu;
+ addNodes(&specSettingMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(specSettingMenu.parentMenu, true);
+ });
+
+ // Web Update
+ updateMenu.parentMenu = &deviceMenu;
+
+ // Failed update menu
+ failedUpdateMenu.parentMenu = &deviceMenu;
+ this->addNodes(&failedUpdateMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF;
+ this->changeMenu(failedUpdateMenu.parentMenu, true);
+ });
+
+ // Device info menu
+ infoMenu.parentMenu = &deviceMenu;
+ this->addNodes(&infoMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF;
+ this->changeMenu(infoMenu.parentMenu, true);
+ });
+
+ Serial.println("Changing to main menu...");
+
+ // Set the current menu to the mainMenu
+ this->changeMenu(&mainMenu, true);
+
+ this->initTime = millis();
+}
+
+//#if (!defined(HAS_ILI9341) && defined(HAS_BUTTONS))
+#ifdef HAS_MINI_KB
+ String MenuFunctions::miniKeyboard(Menu * targetMenu, bool do_pass) {
+ // Prepare a char array and reset temp SSID string
+ extern LinkedList* ssids;
+
+ String ret_val = "";
+
+ bool pressed = true;
+
+ wifi_scan_obj.current_mini_kb_ssid = "";
+
+ #ifdef HAS_MINI_KB
+ if (c_btn.isHeld()) {
+ while (!c_btn.justReleased())
+ delay(1);
+ }
+ #endif
+
+ int str_len = wifi_scan_obj.alfa.length() + 1;
+
+ char char_array[str_len];
+
+ wifi_scan_obj.alfa.toCharArray(char_array, str_len);
+
+ #ifdef HAS_TOUCH
+ uint16_t t_x = 0, t_y = 0;
+
+ #endif
+
+ // Button loop until hold center button
+ #ifdef HAS_BUTTONS
+ //#if !(defined(MARAUDER_V6) || defined(MARAUDER_V6_1) || defined(MARAUDER_CYD_MICRO))
+ while(true) {
+ // Keyboard functions for switch hardware
+ #ifdef HAS_MINI_KB
+ // Cycle char previous
+ #ifdef HAS_L
+ if ((l_btn.justPressed()) || (l_btn.isHeld())) {
+ pressed = true;
+ if (this->mini_kb_index > 0)
+ this->mini_kb_index--;
+ else
+ this->mini_kb_index = str_len - 2;
+
+ targetMenu->list->set(0, MenuNode{String(char_array[this->mini_kb_index]).c_str(), false, TFTCYAN, 0, true, NULL});
+ this->buildButtons(targetMenu);
+
+ while (!l_btn.justReleased()) {
+ l_btn.justPressed();
+ if (!l_btn.isHeld())
+ delay(1);
+ else
+ break;
+ }
+ }
+ #endif
+
+ // Cycle char next
+ #ifdef HAS_R
+ if ((r_btn.justPressed()) || (r_btn.isHeld())) {
+ pressed = true;
+ if (this->mini_kb_index < str_len - 2)
+ this->mini_kb_index++;
+ else
+ this->mini_kb_index = 0;
+
+ targetMenu->list->set(0, MenuNode{String(char_array[this->mini_kb_index]).c_str(), false, TFTCYAN, 0, true, NULL});
+ this->buildButtons(targetMenu, 0, &char_array[this->mini_kb_index]);
+
+ while (!r_btn.justReleased()) {
+ r_btn.justPressed();
+ if (!r_btn.isHeld())
+ delay(1);
+ else
+ break;
+ }
+ }
+ #endif
+
+ //// 5-WAY SWITCH STUFF
+ // Add character
+ #if (defined(HAS_D) && defined(HAS_R))
+ if (d_btn.justPressed()) {
+ pressed = true;
+ wifi_scan_obj.current_mini_kb_ssid.concat(String(char_array[this->mini_kb_index]).c_str());
+ while (!d_btn.justReleased())
+ delay(1);
+ }
+ #endif
+
+ // Remove character
+ #if (defined(HAS_U) && defined(HAS_L))
+ if (u_btn.justPressed()) {
+ pressed = true;
+ wifi_scan_obj.current_mini_kb_ssid.remove(wifi_scan_obj.current_mini_kb_ssid.length() - 1);
+ while (!u_btn.justReleased())
+ delay(1);
+ }
+ #endif
+
+ //// PARTIAL SWITCH STUFF
+ // Advance char or add char
+ #if (defined(HAS_D) && !defined(HAS_R))
+ if (d_btn.justPressed()) {
+ bool was_held = false;
+ pressed = true;
+ while(!d_btn.justReleased()) {
+ d_btn.justPressed();
+
+ // Add letter to string
+ if (d_btn.isHeld()) {
+ wifi_scan_obj.current_mini_kb_ssid.concat(String(char_array[this->mini_kb_index]).c_str());
+ was_held = true;
+ break;
+ }
+ }
+ if (!was_held) {
+ if (this->mini_kb_index < str_len - 2)
+ this->mini_kb_index++;
+ else
+ this->mini_kb_index = 0;
+
+ targetMenu->list->set(0, MenuNode{String(char_array[this->mini_kb_index]).c_str(), false, TFTCYAN, 0, true, NULL});
+ this->buildButtons(targetMenu, 0, &char_array[this->mini_kb_index]);
+ }
+ }
+ #endif
+
+ // Prev char or remove char
+ #if (defined(HAS_U) && !defined(HAS_L))
+ if (u_btn.justPressed()) {
+ bool was_held = false;
+ pressed = true;
+ while(!u_btn.justReleased()) {
+ u_btn.justPressed();
+
+ // Remove letter from string
+ if (u_btn.isHeld()) {
+ wifi_scan_obj.current_mini_kb_ssid.remove(wifi_scan_obj.current_mini_kb_ssid.length() - 1);
+ was_held = true;
+ break;
+ }
+ }
+ if (!was_held) {
+ if (this->mini_kb_index > 0)
+ this->mini_kb_index--;
+ else
+ this->mini_kb_index = str_len - 2;
+
+ targetMenu->list->set(0, MenuNode{String(char_array[this->mini_kb_index]).c_str(), false, TFTCYAN, 0, true, NULL});
+ this->buildButtons(targetMenu);
+ }
+ }
+ #endif
+
+ // Add SSID
+ #if defined(HAS_C) && !defined(MARAUDER_CARDPUTER) && !defined(MARAUDER_CARDPUTER_ADV)
+ if (c_btn.justPressed()) {
+ while (!c_btn.justReleased()) {
+ c_btn.justPressed(); // Need to continue updating button hold status. My shitty library.
+
+ // Exit
+ if (c_btn.isHeld()) {
+ this->changeMenu(targetMenu->parentMenu);
+ return wifi_scan_obj.current_mini_kb_ssid;
+ }
+ delay(1);
+ }
+
+ if (!do_pass) {
+ // If we have a string, add it to list of SSIDs
+ if (wifi_scan_obj.current_mini_kb_ssid != "") {
+ pressed = true;
+ ssid s = {wifi_scan_obj.current_mini_kb_ssid, random(1, 12), {random(256), random(256), random(256), random(256), random(256), random(256)}, false};
+ ssids->unshift(s);
+ wifi_scan_obj.current_mini_kb_ssid = "";
+ }
+ }
+ }
+ #endif
+ #endif
+
+ #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+ for (int i = 0; i < 95; i++) {
+ if ((M5CardputerKeyboard._ascii_list[i] != '(') &&
+ (M5CardputerKeyboard._ascii_list[i] != '`')) {
+ if (this->isKeyPressed(M5CardputerKeyboard._ascii_list[i])) {
+ pressed = true;
+ wifi_scan_obj.current_mini_kb_ssid.concat(M5CardputerKeyboard._ascii_list[i]);
+ }
+ if (this->isKeyPressed(KEY_BACKSPACE)) {
+ pressed = true;
+ wifi_scan_obj.current_mini_kb_ssid.remove(wifi_scan_obj.current_mini_kb_ssid.length() - 1);
+ }
+ }
+ }
+
+ if (!do_pass) {
+ if (this->isKeyPressed('`')) {
+ this->changeMenu(targetMenu->parentMenu, true);
+ return wifi_scan_obj.current_mini_kb_ssid;
+ }
+
+ if (this->isKeyPressed('(')) {
+ if (!do_pass) {
+ if (wifi_scan_obj.current_mini_kb_ssid != "") {
+ pressed = true;
+ ssid s = {wifi_scan_obj.current_mini_kb_ssid, random(1, 12), {random(256), random(256), random(256), random(256), random(256), random(256)}, false};
+ ssids->unshift(s);
+ wifi_scan_obj.current_mini_kb_ssid = "";
+ }
+ }
+ }
+ }
+ else {
+ if (this->isKeyPressed('(')) {
+ this->changeMenu(targetMenu->parentMenu, true);
+ return wifi_scan_obj.current_mini_kb_ssid;
+ }
+
+ if (this->isKeyPressed('`')) {
+ this->changeMenu(targetMenu->parentMenu, true);
+ return "";
+ }
+ }
+
+ #endif
+
+ // Keyboard functions for touch hardware
+ #ifdef HAS_TOUCH
+ bool touched = display_obj.updateTouch(&t_x, &t_y);
+
+ uint8_t menu_button = display_obj.menuButton(&t_x, &t_y, touched);
+
+ // Cycle char previous
+ if (menu_button == UP_BUTTON) {
+ pressed = true;
+ if (this->mini_kb_index > 0)
+ this->mini_kb_index--;
+ else
+ this->mini_kb_index = str_len - 2;
+
+ targetMenu->list->set(0, MenuNode{String(char_array[this->mini_kb_index]).c_str(), false, TFTCYAN, 0, true, NULL});
+ this->buildButtons(targetMenu);
+ while (display_obj.updateTouch(&t_x, &t_y) > 0)
+ delay(1);
+ display_obj.menuButton(&t_x, &t_y, display_obj.updateTouch(&t_x, &t_y));
+ }
+
+ // Cycle char next
+ if (menu_button == DOWN_BUTTON) {
+ pressed = true;
+ if (this->mini_kb_index < str_len - 2)
+ this->mini_kb_index++;
+ else
+ this->mini_kb_index = 0;
+
+ targetMenu->list->set(0, MenuNode{String(char_array[this->mini_kb_index]).c_str(), false, TFTCYAN, 0, true, NULL});
+ this->buildButtons(targetMenu, 0, &char_array[this->mini_kb_index]);
+ while (display_obj.updateTouch(&t_x, &t_y) > 0)
+ delay(1);
+ display_obj.menuButton(&t_x, &t_y, display_obj.updateTouch(&t_x, &t_y));
+ }
+
+ //// 5-WAY SWITCH STUFF
+ // Add character when select button is pressed
+ if (menu_button == SELECT_BUTTON) {
+ pressed = true;
+ wifi_scan_obj.current_mini_kb_ssid.concat(String(char_array[this->mini_kb_index]).c_str());
+ while (display_obj.updateTouch(&t_x, &t_y) > 0)
+ delay(1);
+ display_obj.menuButton(&t_x, &t_y, display_obj.updateTouch(&t_x, &t_y));
+ }
+
+ // Remove character when select button is held
+ if ((display_obj.isTouchHeld()) && (display_obj.menuButton(&t_x, &t_y, touched, true) == SELECT_BUTTON)) {
+ pressed = true;
+ wifi_scan_obj.current_mini_kb_ssid.remove(wifi_scan_obj.current_mini_kb_ssid.length() - 1);
+ while (display_obj.menuButton(&t_x, &t_y, display_obj.updateTouch(&t_x, &t_y)) < 0)
+ delay(1);
+ }
+
+ //// PARTIAL SWITCH STUFF
+ // Advance char or add char
+ #if (defined(HAS_D) && !defined(HAS_R))
+ if (d_btn.justPressed()) {
+ bool was_held = false;
+ pressed = true;
+ while(!d_btn.justReleased()) {
+ d_btn.justPressed();
+
+ // Add letter to string
+ if (d_btn.isHeld()) {
+ wifi_scan_obj.current_mini_kb_ssid.concat(String(char_array[this->mini_kb_index]).c_str());
+ was_held = true;
+ break;
+ }
+ }
+ if (!was_held) {
+ if (this->mini_kb_index < str_len - 2)
+ this->mini_kb_index++;
+ else
+ this->mini_kb_index = 0;
+
+ targetMenu->list->set(0, MenuNode{String(char_array[this->mini_kb_index]).c_str(), false, TFTCYAN, 0, true, NULL});
+ this->buildButtons(targetMenu, 0, &char_array[this->mini_kb_index]);
+ }
+ }
+ #endif
+
+ // Prev char or remove char
+ #if (defined(HAS_U) && !defined(HAS_L))
+ if (u_btn.justPressed()) {
+ bool was_held = false;
+ pressed = true;
+ while(!u_btn.justReleased()) {
+ u_btn.justPressed();
+
+ // Remove letter from string
+ if (u_btn.isHeld()) {
+ wifi_scan_obj.current_mini_kb_ssid.remove(wifi_scan_obj.current_mini_kb_ssid.length() - 1);
+ was_held = true;
+ break;
+ }
+ }
+ if (!was_held) {
+ if (this->mini_kb_index > 0)
+ this->mini_kb_index--;
+ else
+ this->mini_kb_index = str_len - 2;
+
+ targetMenu->list->set(0, MenuNode{String(char_array[this->mini_kb_index]).c_str(), false, TFTCYAN, 0, true, NULL});
+ this->buildButtons(targetMenu);
+ }
+ }
+ #endif
+
+ // Exit if UP button is held
+ if ((display_obj.isTouchHeld()) && (display_obj.menuButton(&t_x, &t_y, touched, true) == UP_BUTTON)) {
+ display_obj.clearScreen();
+ while (display_obj.menuButton(&t_x, &t_y, display_obj.updateTouch(&t_x, &t_y)) < 0)
+ delay(1);
+
+ // Reset the touch keys so we don't activate the keys when we go back
+ display_obj.menuButton(&t_x, &t_y, display_obj.updateTouch(&t_x, &t_y));
+ this->changeMenu(targetMenu->parentMenu, true);
+ return wifi_scan_obj.current_mini_kb_ssid;
+ }
+
+ // If the screen is touched but none of the keys are used, don't refresh display
+ if (menu_button < 0)
+ pressed = false;
+
+ #endif
+
+ // Display info on screen
+ if (pressed) {
+ this->displayCurrentMenu();
+ display_obj.tft.setTextWrap(false);
+ display_obj.tft.fillRect(0, SCREEN_HEIGHT / 3, SCREEN_WIDTH, STATUS_BAR_WIDTH, TFT_BLACK);
+ display_obj.tft.fillRect(0, SCREEN_HEIGHT / 3 + TEXT_HEIGHT * 2, SCREEN_WIDTH, STATUS_BAR_WIDTH, TFT_BLACK);
+ display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
+ display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
+ display_obj.tft.println(wifi_scan_obj.current_mini_kb_ssid + "\n");
+ display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK);
+
+ display_obj.tft.println(ssids->get(0).essid);
+
+ display_obj.tft.setTextColor(TFT_ORANGE, TFT_BLACK);
+ #ifdef HAS_MINI_KB
+ #if !defined(MARAUDER_CARDPUTER) && !defined(MARAUDER_CARDPUTER_ADV)
+ display_obj.tft.println("U/D - Rem/Add Char");
+ display_obj.tft.println("L/R - Prev/Nxt Char");
+ #endif
+ if (!do_pass) {
+ #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+ display_obj.tft.println("Enter - Save");
+ display_obj.tft.println("Esc - Exit");
+ #else
+ display_obj.tft.println("C - Save");
+ display_obj.tft.println("C(Hold) - Exit");
+ #endif
+ }
+ else {
+ #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+ display_obj.tft.println("Enter - Enter");
+ #else
+ display_obj.tft.println("C(Hold) - Enter");
+ #endif
+ }
+ #endif
+
+ #ifdef HAS_TOUCH
+ display_obj.tft.println("U/D - Prev/Nxt Char");
+ display_obj.tft.println("C - Add Char");
+ display_obj.tft.println("C(Hold) - Rem Char");
+ display_obj.tft.println("U(Hold) - Enter");
+ #endif
+ pressed = false;
+ }
+ }
+ //#endif
+ #endif
+ }
+#endif
+
+void MenuFunctions::setupSDFileList(bool update) {
+ sd_obj.sd_files->clear();
+
+ delete sd_obj.sd_files;
+
+ sd_obj.sd_files = new LinkedList();
+
+ if (!update)
+ sd_obj.listDirToLinkedList(sd_obj.sd_files);
+ else
+ sd_obj.listDirToLinkedList(sd_obj.sd_files, "/", ".bin");
+}
+
+void MenuFunctions::buildSDFileMenu(bool update) {
+ this->setupSDFileList(update);
+
+ sdDeleteMenu.list->clear();
+ delete sdDeleteMenu.list;
+ sdDeleteMenu.list = new LinkedList();
+
+ if (!update)
+ sdDeleteMenu.name = "SD Files";
+ else
+ sdDeleteMenu.name = "Bin Files";
+
+ this->addNodes(&sdDeleteMenu, text09, TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(sdDeleteMenu.parentMenu, true);
+ });
+
+ if (!update) {
+ this->addNodes(&sdDeleteMenu, "Delete Selected", TFTORANGE, 0, [this]() {
+ for (int x = 0; x < sd_obj.sd_files->size(); x++) {
+ if (current_menu->list->get(x + 2).selected) {
+ if (sd_obj.removeFile("/" + sd_obj.sd_files->get(x))) {
+ Serial.println("Deleted /" + sd_obj.sd_files->get(x));
+ display_obj.clearScreen();
+ display_obj.tft.setTextWrap(false);
+ display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
+ display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
+ display_obj.tft.println("Deleting /" + sd_obj.sd_files->get(x) + "...");
+ }
+ }
+ }
+ this->buildSDFileMenu();
+ this->changeMenu(&sdDeleteMenu, true);
+ });
+ }
+
+ if (!update) {
+ for (int x = 0; x < sd_obj.sd_files->size(); x++) {
+ this->addNodes(&sdDeleteMenu, sd_obj.sd_files->get(x).c_str(), TFTCYAN, SD_UPDATE, [this, x]() {
+ // Change selection status of menu node
+ MenuNode new_node = current_menu->list->get(x + 2);
+ new_node.selected = !current_menu->list->get(x + 2).selected;
+ current_menu->list->set(x + 2, new_node);
+ });
+ }
+ }
+ else {
+ for (int x = 0; x < sd_obj.sd_files->size(); x++) {
+ this->addNodes(&sdDeleteMenu, sd_obj.sd_files->get(x).c_str(), TFTCYAN, SD_UPDATE, [this, x]() {
+ wifi_scan_obj.currentScanMode = OTA_UPDATE;
+ this->changeMenu(&failedUpdateMenu, true);
+ sd_obj.runUpdate("/" + sd_obj.sd_files->get(x));
+ });
+ }
+ }
+}
+
+
+// Function to add MenuNodes to a menu
+void MenuFunctions::addNodes(Menu * menu, const char* name, uint8_t color, int place, std::function callable, bool selected)
+{
+ //Serial.println("Building node: " + name);
+ menu->list->add(MenuNode{String(name), false, color, place, selected, callable});
+}
+
+void MenuFunctions::setGraphScale(float scale) {
+ this->_graph_scale = scale;
+}
+
+float MenuFunctions::calculateGraphScale(uint8_t value) {
+ if ((value * this->_graph_scale < GRAPH_VERT_LIM) && (value * this->_graph_scale > GRAPH_VERT_LIM * 0.75)) {
+ return this->_graph_scale; // No scaling needed if the value is within the limit
+ }
+
+ if (value < GRAPH_VERT_LIM)
+ return 1.0;
+
+ // Calculate the multiplier proportionally
+ return (0.75 * GRAPH_VERT_LIM) / value;
+}
+
+float MenuFunctions::calculateGraphScale(int16_t value) {
+ if ((value * this->_graph_scale < GRAPH_VERT_LIM) && (value * this->_graph_scale > GRAPH_VERT_LIM * 0.75)) {
+ return this->_graph_scale; // No scaling needed if the value is within the limit
+ }
+
+ if (value < GRAPH_VERT_LIM)
+ return 1.0;
+
+ // Calculate the multiplier proportionally
+ return (0.75 * GRAPH_VERT_LIM) / value;
+}
+
+float MenuFunctions::graphScaleCheck(const int16_t array[SCREEN_WIDTH]) {
+ int16_t maxValue = 0;
+
+ // Iterate through the array to find the highest value
+ for (int16_t i = 0; i < SCREEN_WIDTH; i++) {
+ if (array[i] > maxValue) {
+ maxValue = array[i];
+ }
+ }
+
+ // If the highest value exceeds GRAPH_VERT_LIM, call calculateMultiplier
+ if (maxValue > GRAPH_VERT_LIM) {
+ return this->calculateGraphScale(maxValue);
+ }
+
+ // If the highest value does not exceed GRAPH_VERT_LIM, return 1.0
+ return 1.0;
+}
+
+float MenuFunctions::graphScaleCheckSmall(const uint8_t array[CHAN_PER_PAGE]) {
+ uint8_t maxValue = 0;
+
+ // Iterate through the array to find the highest value
+ for (uint8_t i = 0; i < CHAN_PER_PAGE; i++) {
+ if (array[i] > maxValue) {
+ maxValue = array[i];
+ }
+ }
+
+ // If the highest value exceeds GRAPH_VERT_LIM, call calculateMultiplier
+ if (maxValue > GRAPH_VERT_LIM) {
+ return this->calculateGraphScale(maxValue);
+ }
+
+ // If the highest value does not exceed GRAPH_VERT_LIM, return 1.0
+ return 1.0;
+}
+
+void MenuFunctions::drawMaxLine(int16_t value, uint16_t color) {
+ display_obj.tft.drawLine(0, TFT_HEIGHT - (value * this->_graph_scale), TFT_WIDTH, TFT_HEIGHT - (value * this->_graph_scale), color);
+ display_obj.tft.setCursor(0, TFT_HEIGHT - (value * this->_graph_scale));
+ display_obj.tft.setTextColor(color, TFT_BLACK);
+ display_obj.tft.setTextSize(1);
+ display_obj.tft.println((String)(value / BASE_MULTIPLIER));
+}
+
+void MenuFunctions::drawMaxLine(uint8_t value, uint16_t color) {
+ //display_obj.tft.drawLine(0, TFT_HEIGHT - (value * this->_graph_scale), TFT_WIDTH, TFT_HEIGHT - (value * this->_graph_scale), color);
+ display_obj.tft.setCursor(0, TFT_HEIGHT - (value * this->_graph_scale));
+ display_obj.tft.setTextColor(color, TFT_BLACK);
+ display_obj.tft.setTextSize(1);
+ display_obj.tft.println((String)value);
+}
+
+void MenuFunctions::drawGraphSmall(uint8_t *values) {
+ uint8_t maxValue = 0;
+ //(i + (CHAN_PER_PAGE * (this->activity_page - 1)))
+
+ int bar_width = SCREEN_WIDTH / (CHAN_PER_PAGE * 2);
+ //display_obj.tft.fillRect(0, TFT_HEIGHT / 2 + 1, SCREEN_WIDTH, (TFT_HEIGHT / 2) + 1, TFT_BLACK);
+
+ #ifndef HAS_DUAL_BAND
+ for (int i = 1; i < CHAN_PER_PAGE + 1; i++) {
+ int targ_val = i + (CHAN_PER_PAGE * (wifi_scan_obj.activity_page - 1)) - 1;
+ int x_mult = (i * 2) - 1;
+ int x_coord = (SCREEN_WIDTH / (CHAN_PER_PAGE * 2)) * (x_mult - 1);
+
+ if (values[targ_val] > maxValue) {
+ maxValue = values[targ_val];
+ }
+
+ if (values[targ_val] * this->_graph_scale <= GRAPH_VERT_LIM) {
+ display_obj.tft.fillRect(x_coord, SCREEN_HEIGHT / 2 + 1, bar_width, SCREEN_HEIGHT / 2 + 1, TFT_BLACK);
+ display_obj.tft.fillRect(x_coord, SCREEN_HEIGHT - (values[targ_val] * this->_graph_scale), bar_width, values[targ_val] * this->_graph_scale, TFT_CYAN);
+ }
+
+ display_obj.tft.drawLine(x_coord - 2, SCREEN_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 2), x_coord - 2, SCREEN_HEIGHT, TFT_WHITE);
+ }
+ #else
+ for (int i = 1; i < CHAN_PER_PAGE + 1; i++) {
+ int targ_val = i + (CHAN_PER_PAGE * (wifi_scan_obj.activity_page - 1)) - 1;
+ int x_mult = (i * 2) - 1;
+ int x_coord = (SCREEN_WIDTH / (CHAN_PER_PAGE * 2)) * (x_mult - 1);
+
+ if (values[targ_val] > maxValue) {
+ maxValue = values[targ_val];
+ }
+
+ if (values[targ_val] * this->_graph_scale <= GRAPH_VERT_LIM) {
+ display_obj.tft.fillRect(x_coord, SCREEN_HEIGHT / 2 + 1, bar_width + 3, SCREEN_HEIGHT / 2 + 1, TFT_BLACK);
+ display_obj.tft.fillRect(x_coord, SCREEN_HEIGHT - (values[targ_val] * this->_graph_scale), bar_width, values[targ_val] * this->_graph_scale, TFT_CYAN);
+ }
+
+ display_obj.tft.drawLine(x_coord - 2, SCREEN_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 2), x_coord - 2, SCREEN_HEIGHT, TFT_WHITE);
+ }
+ #endif
+
+ this->drawMaxLine(maxValue, TFT_GREEN); // Draw max
+}
+
+void MenuFunctions::drawGraph(int16_t *values) {
+ #if !defined(MARAUDER_CARDPUTER) && !defined(MARAUDER_CARDPUTER_ADV)
+ int width = TFT_WIDTH;
+ #else
+ int width = SCREEN_WIDTH;
+ #endif
+
+ int16_t maxValue = 0;
+ int total = 0;
+ for (int i = width - 1; i >= 0; i--) {
+ if (values[i] >= 0) {
+ total = total + values[i];
+ if (values[i] > maxValue) {
+ maxValue = values[i];
+ }
+ #if !defined(MARAUDER_CARDPUTER) && !defined(MARAUDER_CARDPUTER_ADV)
+ display_obj.tft.drawLine(i, TFT_HEIGHT, i, TFT_HEIGHT - GRAPH_VERT_LIM, TFT_BLACK);
+ display_obj.tft.drawLine(i, TFT_HEIGHT, i, TFT_HEIGHT - (values[i] * this->_graph_scale), TFT_CYAN);
+ #else
+ display_obj.tft.drawLine(i, TFT_WIDTH, i, TFT_WIDTH - GRAPH_VERT_LIM, TFT_BLACK);
+ display_obj.tft.drawLine(i, TFT_WIDTH, i, TFT_WIDTH - (values[i] * this->_graph_scale), TFT_CYAN);
+ display_obj.tft.setCursor(0, 0);
+ display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK);
+ #endif
+ }
+ else {
+ int16_t ch_val = values[i] * -1;
+ #if !defined(MARAUDER_CARDPUTER) && !defined(MARAUDER_CARDPUTER_ADV)
+ display_obj.tft.drawLine(i, TFT_HEIGHT, i, TFT_HEIGHT - GRAPH_VERT_LIM, TFT_BLACK);
+ display_obj.tft.drawLine(i, TFT_HEIGHT, i, TFT_HEIGHT - GRAPH_VERT_LIM, TFT_RED);
+ display_obj.tft.setCursor(i, TFT_HEIGHT - GRAPH_VERT_LIM);
+ #else
+ display_obj.tft.drawLine(i, TFT_WIDTH, i, TFT_WIDTH - GRAPH_VERT_LIM, TFT_BLACK);
+ display_obj.tft.drawLine(i, TFT_WIDTH, i, TFT_WIDTH - GRAPH_VERT_LIM, TFT_RED);
+ display_obj.tft.setCursor(i, TFT_WIDTH - GRAPH_VERT_LIM);
+ #endif
+ display_obj.tft.setTextColor(TFT_BLACK, TFT_RED);
+ display_obj.tft.setTextSize(1);
+ display_obj.tft.println((String)ch_val);
+ }
+ }
+
+ this->drawMaxLine(maxValue, TFT_GREEN); // Draw max
+ this->drawMaxLine((int16_t)(total / TFT_WIDTH), TFT_ORANGE); // Draw average
+}
+
+void MenuFunctions::renderGraphUI(uint8_t scan_mode) {
+ display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK);
+ if (scan_mode == WIFI_SCAN_CHAN_ANALYZER)
+ display_obj.tft.drawCentreString("Frames/" + (String)BANNER_TIME + "ms", SCREEN_WIDTH / 2, SCREEN_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 2), 1);
+ else if (scan_mode == BT_SCAN_ANALYZER)
+ display_obj.tft.drawCentreString("BLE Beacons/" + (String)BANNER_TIME + "ms", SCREEN_WIDTH / 2, SCREEN_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 2), 1);
+ display_obj.tft.drawLine(0, SCREEN_HEIGHT - GRAPH_VERT_LIM - 1, SCREEN_WIDTH, SCREEN_HEIGHT - GRAPH_VERT_LIM - 1, TFT_WHITE);
+ display_obj.tft.setCursor(0, SCREEN_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 8));
+ display_obj.tft.setTextSize(1);
+ display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK);
+ display_obj.tft.println("Max");
+ display_obj.tft.setTextColor(TFT_ORANGE, TFT_BLACK);
+ display_obj.tft.println("Average");
+ display_obj.tft.setTextColor(TFT_RED, TFT_BLACK);
+ if (scan_mode != BT_SCAN_ANALYZER)
+ display_obj.tft.println("Channel Marker");
+}
+
+uint16_t MenuFunctions::getColor(uint16_t color) {
+ if (color == TFTWHITE) return TFT_WHITE;
+ else if (color == TFTCYAN) return TFT_CYAN;
+ else if (color == TFTBLUE) return TFT_BLUE;
+ else if (color == TFTRED) return TFT_RED;
+ else if (color == TFTGREEN) return TFT_GREEN;
+ else if (color == TFTGREY) return TFT_LIGHTGREY;
+ else if (color == TFTGRAY) return TFT_LIGHTGREY;
+ else if (color == TFTMAGENTA) return TFT_MAGENTA;
+ else if (color == TFTVIOLET) return TFT_VIOLET;
+ else if (color == TFTORANGE) return TFT_ORANGE;
+ else if (color == TFTYELLOW) return TFT_YELLOW;
+ else if (color == TFTLIGHTGREY) return TFT_LIGHTGREY;
+ else if (color == TFTPURPLE) return TFT_PURPLE;
+ else if (color == TFTNAVY) return TFT_NAVY;
+ else if (color == TFTSILVER) return TFT_SILVER;
+ else if (color == TFTDARKGREY) return TFT_DARKGREY;
+ else if (color == TFTSKYBLUE) return TFT_SKYBLUE;
+ else if (color == TFTLIME) return 0x97e0;
+ else return color;
+}
+
+// Function to change menu
+void MenuFunctions::changeMenu(Menu* menu, bool simple_change) {
+ if (!simple_change) {
+ //display_obj.initScrollValues();
+ //display_obj.setupScrollArea(TOP_FIXED_AREA, BOT_FIXED_AREA);
+ display_obj.init();
+
+ #ifdef HAS_ILI9341
+ extern void backlightOn();
+ backlightOn();
+ #endif
+ }
+ current_menu = menu;
+
+ current_menu->selected = 0;
+
+ buildButtons(menu);
+
+ displayCurrentMenu();
+
+ //#ifdef MARAUDER_V8
+ // digitalWrite(TFT_BL, HIGH);
+ //#endif
+}
+
+void MenuFunctions::buildButtons(Menu *menu, int starting_index, const char* button_name) {
+ if (menu->list == NULL || menu->list->size() == 0)
+ return;
+
+ if (starting_index >= menu->list->size())
+ starting_index = menu->list->size() - BUTTON_SCREEN_LIMIT;
+ if (starting_index < 0)
+ starting_index = 0;
+
+ this->menu_start_index = starting_index;
+
+ uint8_t visible_buttons = min(BUTTON_SCREEN_LIMIT, menu->list->size() - starting_index);
+
+ for (uint8_t i = 0; i < visible_buttons; i++) {
+ MenuNode node = menu->list->get(starting_index + i);
+ uint16_t color = (node.icon == SETTINGS && node.color == TFTLIGHTGREY) ? (node.selected ? TFT_GREEN : TFT_RED) : this->getColor(node.color);
+
+ char buf[64];
+
+ if (button_name != nullptr && button_name[0] != '\0') {
+ strncpy(buf, button_name, sizeof(buf));
+ buf[sizeof(buf) - 1] = '\0';
+ } else {
+ node.name.toCharArray(buf, sizeof(buf));
+ }
+
+ display_obj.key[i].initButton(&display_obj.tft,
+ KEY_X,
+ KEY_Y + i * (KEY_H + KEY_SPACING_Y),
+ KEY_W,
+ KEY_H,
+ TFT_BLACK,
+ TFT_BLACK,
+ color,
+ buf,
+ KEY_TEXTSIZE);
+
+ #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+ display_obj.key[i].setLabelDatum(BUTTON_PADDING - (KEY_W / 2), 4, ML_DATUM);
+ #else
+ display_obj.key[i].setLabelDatum(BUTTON_PADDING - (KEY_W / 2), 2, ML_DATUM);
+ #endif
+ }
+
+ for (int i = BUTTON_ARRAY_LEN; i < BUTTON_ARRAY_LEN + 3; i++) {
+ uint16_t x = TFT_WIDTH / 2;
+ uint16_t y = TFT_HEIGHT / 3 * (i - BUTTON_ARRAY_LEN) + ((TFT_HEIGHT / 3) / 2);
+ uint16_t w = TFT_WIDTH;
+ uint16_t h = TFT_HEIGHT / 3 - 1;
+
+ display_obj.key[i].initButton(&display_obj.tft,
+ x,
+ y,
+ w,
+ h,
+ TFT_LIGHTGREY,
+ TFT_BLACK,
+ TFT_BLACK,
+ "Chicken",
+ 1);
+ }
+}
+
+void MenuFunctions::displayCurrentMenu(int start_index)
+{
+ //Serial.println(F("Displaying current menu..."));
+ display_obj.clearScreen();
+ display_obj.updateBanner(current_menu->name);
+ display_obj.tft.setTextColor(TFT_LIGHTGREY, TFT_DARKGREY);
+ this->drawStatusBar();
+
+ if (current_menu->list != NULL)
+ {
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.setFreeFont(MENU_FONT);
+ #endif
+
+ #ifdef HAS_MINI_SCREEN
+ display_obj.tft.setFreeFont(NULL);
+ display_obj.tft.setTextSize(1);
+ #endif
+
+ for (uint16_t i = start_index; i < min(start_index + BUTTON_SCREEN_LIMIT, current_menu->list->size()); i++)
+ {
+ if (!current_menu || !current_menu->list || i >= current_menu->list->size())
+ continue;
+ uint16_t color = this->getColor(current_menu->list->get(i).color);
+ #ifdef HAS_FULL_SCREEN
+ bool is_setting_node = (current_menu->list->get(i).icon == SETTINGS && current_menu->list->get(i).color == TFTLIGHTGREY);
+ if (is_setting_node && current_menu->selected == i) {
+ uint16_t setting_color = current_menu->list->get(i).selected ? TFT_GREEN : TFT_RED;
+ display_obj.key[i - start_index].initButton(&display_obj.tft, KEY_X, KEY_Y + (i - start_index) * (KEY_H + KEY_SPACING_Y), KEY_W, KEY_H, TFT_BLACK, TFT_LIGHTGREY, setting_color, (char*)"", KEY_TEXTSIZE);
+ display_obj.key[i - start_index].drawButton(false, current_menu->list->get(i).name);
+ display_obj.tft.drawXBitmap(0,
+ KEY_Y + (i - start_index) * (KEY_H + KEY_SPACING_Y) - (ICON_H / 2),
+ menu_icons[current_menu->list->get(i).icon],
+ ICON_W,
+ ICON_H,
+ TFT_BLACK,
+ TFT_LIGHTGREY);
+ } else if ((!is_setting_node && current_menu->list->get(i).selected) || (current_menu->selected == i)) {
+ display_obj.key[i - start_index].drawButton(true, current_menu->list->get(i).name);
+ if ((current_menu->list->get(i).name != text09) && (current_menu->list->get(i).icon != 255))
+ display_obj.tft.drawXBitmap(0,
+ KEY_Y + (i - start_index) * (KEY_H + KEY_SPACING_Y) - (ICON_H / 2),
+ menu_icons[current_menu->list->get(i).icon],
+ ICON_W,
+ ICON_H,
+ TFT_BLACK,
+ color);
+ } else {
+ display_obj.key[i - start_index].drawButton(false, current_menu->list->get(i).name);
+ if ((current_menu->list->get(i).name != text09) && (current_menu->list->get(i).icon != 255))
+ display_obj.tft.drawXBitmap(0,
+ KEY_Y + (i - start_index) * (KEY_H + KEY_SPACING_Y) - (ICON_H / 2),
+ menu_icons[current_menu->list->get(i).icon],
+ ICON_W,
+ ICON_H,
+ TFT_BLACK,
+ is_setting_node ? TFT_LIGHTGREY : color);
+ }
+
+ #endif
+
+ #ifdef HAS_MINI_SCREEN
+ if ((current_menu->selected == i) || ((current_menu->list->get(i).icon != SETTINGS || current_menu->list->get(i).color != TFTLIGHTGREY) && current_menu->list->get(i).selected))
+ this->drawMiniMenuButton(i - start_index, i, true);
+ else
+ this->drawMiniMenuButton(i - start_index, i, false);
+ #endif
+ }
+ display_obj.tft.setFreeFont(NULL);
+ }
+
+ this->displayMenuButtons();
+}
+
+// ============================================================
+// BRIGHTNESS ADJUSTMENT MODE
+// Hold top/bottom zone 1.5s to enter. TAP TOP = brighter, TAP BOTTOM = dimmer.
+// TAP MIDDLE or wait 3s = save & exit.
+// ============================================================
+#ifndef HAS_MINI_SCREEN
+ void MenuFunctions::brightnessMode() {
+ extern void brightnessSave(uint8_t level);
+ extern uint8_t getBrightnessLevel();
+
+ const uint8_t levels[] = {26, 51, 77, 102, 128, 153, 179, 204, 230, 255};
+ const uint8_t numLevels = 10;
+ uint8_t level = getBrightnessLevel();
+
+ // LEDC write compatibility (2.x vs 3.x board package)
+ #if ESP_ARDUINO_VERSION_MAJOR >= 3
+ #define BL_PREVIEW(duty) ledcWrite(TFT_BL, (duty))
+ #else
+ #define BL_PREVIEW(duty) ledcWrite(0, (duty))
+ #endif
+
+ display_obj.tft.fillScreen(TFT_BLACK);
+ display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
+ display_obj.tft.drawCentreString("BRIGHTNESS", TFT_WIDTH/2, 30, 2);
+
+ display_obj.tft.setTextColor(TFT_DARKGREY, TFT_BLACK);
+ display_obj.tft.drawCentreString("TAP TOP = BRIGHTER", TFT_WIDTH/2, 10, 1);
+ display_obj.tft.drawCentreString("TAP BOTTOM = DIMMER", TFT_WIDTH/2, TFT_HEIGHT - 20, 1);
+ display_obj.tft.setTextColor(TFT_RED, TFT_BLACK);
+ display_obj.tft.drawCentreString("TAP MIDDLE or WAIT 3s = SAVE", TFT_WIDTH/2, TFT_HEIGHT/2 + 50, 1);
+
+ auto drawBar = [&]() {
+ uint16_t barX = 30, barY = TFT_HEIGHT/2 - 25, barW = TFT_WIDTH - 60, barH = 30;
+ display_obj.tft.drawRect(barX, barY, barW, barH, TFT_WHITE);
+ uint16_t fillW = (barW - 4) * (level + 1) / numLevels;
+ display_obj.tft.fillRect(barX + 2, barY + 2, barW - 4, barH - 4, TFT_BLACK);
+ display_obj.tft.fillRect(barX + 2, barY + 2, fillW, barH - 4, TFT_CYAN);
+ display_obj.tft.fillRect(0, barY + barH + 5, TFT_WIDTH, 20, TFT_BLACK);
+ display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK);
+ String pct = String(levels[level] * 100 / 255) + "%";
+ display_obj.tft.drawCentreString(pct, TFT_WIDTH/2, barY + barH + 8, 2);
+ };
+ drawBar();
+
+ uint16_t zoneUp = TFT_HEIGHT * 25 / 100;
+ uint16_t zoneDown = TFT_HEIGHT * 75 / 100;
+ uint32_t lastTouch = millis();
+
+ while (true) {
+ // Auto-save after 3s of no touch
+ if (millis() - lastTouch >= 3000) {
+ brightnessSave(level);
+ break;
+ }
+
+ uint16_t tx, ty;
+ if (display_obj.updateTouch(&tx, &ty)) {
+ lastTouch = millis();
+ // Wait for release
+ while (display_obj.updateTouch(&tx, &ty)) delay(10);
+
+ if (ty < zoneUp) {
+ if (level < numLevels - 1) {
+ level++;
+ BL_PREVIEW(levels[level]);
+ drawBar();
+ }
+ } else if (ty >= zoneDown) {
+ if (level > 0) {
+ level--;
+ BL_PREVIEW(levels[level]);
+ drawBar();
+ }
+ } else {
+ // Middle = save now
+ brightnessSave(level);
+ break;
+ }
+ delay(150);
+ }
+ delay(30);
+ }
+
+ #undef BL_PREVIEW
+ this->changeMenu(current_menu, true);
+ }
+#endif
+
+#endif
+
+
+
diff --git a/esp32_marauder/WiFiScan.cpp b/esp32_marauder/WiFiScan.cpp
index dcf4e22f5..80dcf91f0 100644
--- a/esp32_marauder/WiFiScan.cpp
+++ b/esp32_marauder/WiFiScan.cpp
@@ -2093,7 +2093,7 @@ void WiFiScan::setNetworkInfo() {
this->subnet = WiFi.subnetMask();
}
-void WiFiScan::showNetworkInfo(bool show_display) { // GCOVR_EXCL_LINE -- host tests have no TFT.
+void WiFiScan::showNetworkInfo() {
Serial.print(F("IP address: "));
Serial.println(this->ip_addr);
Serial.print(F("Gateway: "));
@@ -2104,7 +2104,6 @@ void WiFiScan::showNetworkInfo(bool show_display) { // GCOVR_EXCL_LINE -- host t
Serial.println(WiFi.macAddress());
#ifdef HAS_SCREEN
- if (show_display) { // GCOVR_EXCL_LINE
display_obj.tft.println("\nConnected!");
display_obj.tft.print("IP address: ");
display_obj.tft.println(this->ip_addr);
@@ -2116,53 +2115,9 @@ void WiFiScan::showNetworkInfo(bool show_display) { // GCOVR_EXCL_LINE -- host t
display_obj.tft.println(WiFi.macAddress());
display_obj.tft.println("Returning...");
delay(2000);
- } // GCOVR_EXCL_LINE
#endif
}
-// GCOVR_EXCL_START -- scanner presentation requires the hardware TFT renderer.
-void WiFiScan::resetNetworkScanDisplay(const String& target_line, const String& status_line) {
- this->network_scan_result_count = 0;
-
- #ifdef HAS_SCREEN
- // Scanner output uses the shared scrolling renderer. Reset its retained
- // rows and the TFT content so connection-dialog text cannot leak through.
- display_obj.display_buffer->clear();
- #ifdef SCREEN_BUFFER
- display_obj.screen_buffer->clear();
- #endif
- uint16_t content_top = TFT_HEIGHT / 6;
- #ifdef HAS_TOUCH
- content_top = (TFT_HEIGHT / 6) * 1.3;
- #endif
- #ifdef MARAUDER_PANCAKE
- content_top = display_obj.TOP_FIXED_AREA_2;
- #endif
- display_obj.tft.fillRect(0, content_top, TFT_WIDTH, TFT_HEIGHT - content_top, TFT_BLACK);
- display_obj.tft.setFreeFont(NULL);
- display_obj.tft.setTextSize(1);
- display_obj.tft.setTextWrap(false);
- display_obj.display_buffer->add(String(WHITE_KEY) + target_line);
- display_obj.display_buffer->add(String(CYAN_KEY) + status_line);
- #endif
-}
-
-void WiFiScan::addNetworkScanDisplayResult(const String& result_line) {
- this->network_scan_result_count++;
- #ifdef HAS_SCREEN
- display_obj.display_buffer->add(String(GREEN_KEY) + result_line);
- #endif
-}
-
-void WiFiScan::finishNetworkScanDisplay(const String& result_label) {
- #ifdef HAS_SCREEN
- display_obj.display_buffer->add(
- String(CYAN_KEY) + "Done - " + String(this->network_scan_result_count) + " " + result_label
- );
- #endif
-}
-// GCOVR_EXCL_STOP
-
bool WiFiScan::joinWiFi(String ssid, String password, bool gui) {
static const char * btns[] ={text16, ""};
int count = 0;
@@ -3408,21 +3363,14 @@ void WiFiScan::RunPingScan(uint8_t scan_mode, uint16_t color) {
#endif
this->prepareScanStage(TFT_RED, TFT_BLACK);
#endif
- this->current_scan_ip = getNetworkIP(this->ip_addr, this->subnet);
- this->last_scan_ip = IPAddress(0, 0, 0, 0);
+ this->current_scan_ip = this->gateway;
//Serial.print(F("Cleared IPs: "));
this->clearList(CLEAR_IPS);
if (scan_mode == WIFI_PING_SCAN)
Serial.println(F("Starting Ping Scan with..."));
else if (scan_mode == WIFI_ARP_SCAN)
Serial.println(F("Starting ARP Scan with..."));
- // GCOVR_EXCL_START -- scanner presentation requires the hardware TFT renderer.
- this->showNetworkInfo(false);
- this->resetNetworkScanDisplay(
- String("Local ") + this->ip_addr.toString(),
- scan_mode == WIFI_PING_SCAN ? "Scanning live hosts..." : "Scanning ARP neighbors..."
- );
- // GCOVR_EXCL_STOP
+ this->showNetworkInfo();
if (scan_mode == WIFI_PING_SCAN)
buffer_obj.append(F("Starting Ping Scan with..."));
@@ -3494,34 +3442,11 @@ void WiFiScan::RunPortScanAll(uint8_t scan_mode, uint16_t color) {
(scan_mode == WIFI_SCAN_DNS) ||
(scan_mode == WIFI_SCAN_HTTP) ||
(scan_mode == WIFI_SCAN_HTTPS) ||
- (scan_mode == WIFI_SCAN_RDP)) {
- this->current_scan_ip = getNetworkIP(this->ip_addr, this->subnet);
- this->last_scan_ip = IPAddress(0, 0, 0, 0);
- }
+ (scan_mode == WIFI_SCAN_RDP))
+ this->current_scan_ip = this->gateway;
Serial.println(F("Starting Port Scan with..."));
- // GCOVR_EXCL_START -- scanner presentation requires the hardware TFT renderer.
- this->showNetworkInfo(false);
-
- String scan_target;
- String scan_status;
- if (scan_mode == WIFI_PORT_SCAN_ALL) {
- scan_target = String("Target ") + this->current_scan_ip.toString();
- scan_status = "Scanning ports 1-65535...";
- }
- else {
- const uint16_t service_port =
- scan_mode == WIFI_SCAN_SSH ? 22 :
- scan_mode == WIFI_SCAN_TELNET ? 23 :
- scan_mode == WIFI_SCAN_SMTP ? 25 :
- scan_mode == WIFI_SCAN_DNS ? 53 :
- scan_mode == WIFI_SCAN_HTTP ? 80 :
- scan_mode == WIFI_SCAN_HTTPS ? 443 : 3389;
- scan_target = String("Local ") + this->ip_addr.toString();
- scan_status = String("Scanning service port ") + String(service_port) + "...";
- }
- this->resetNetworkScanDisplay(scan_target, scan_status);
- // GCOVR_EXCL_STOP
+ this->showNetworkInfo();
buffer_obj.append(F("Starting Port Scan with..."));
this->writeNetworkInfo();
@@ -10543,77 +10468,40 @@ bool WiFiScan::checkHostPort(IPAddress ip, uint16_t port, uint16_t timeout) {
return false;
}
-IPAddress WiFiScan::advanceScanIP() {
- do {
- this->current_scan_ip = getNextIP(this->current_scan_ip, this->subnet);
- } while ((this->current_scan_ip != IPAddress(0, 0, 0, 0)) &&
- (this->current_scan_ip == this->ip_addr));
-
- if (this->current_scan_ip != IPAddress(0, 0, 0, 0)) {
- this->last_scan_ip = this->current_scan_ip;
- }
- return this->current_scan_ip;
-}
-
-// GCOVR_EXCL_START -- ARP discovery requires a live lwIP station interface.
-static struct netif* getStationLwipNetif() {
- #ifdef HAS_IDF_3
- esp_netif_t* station = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF");
- if (station == nullptr)
- return nullptr;
-
- return static_cast(esp_netif_get_netif_impl(station));
- #else
- void* station = nullptr;
- if (tcpip_adapter_get_netif(TCPIP_ADAPTER_IF_STA, &station) != ESP_OK)
- return nullptr;
-
- return static_cast(station);
- #endif
-}
-
-static bool findStationARP(struct netif* station, const ip4_addr_t* ip) {
- const ip4_addr_t* resolved_ip = nullptr;
- struct eth_addr* resolved_mac = nullptr;
-
- #ifdef HAS_IDF_3
- LOCK_TCPIP_CORE();
- #endif
- const bool found = etharp_find_addr(station, ip, &resolved_mac, &resolved_ip) >= 0;
- #ifdef HAS_IDF_3
- UNLOCK_TCPIP_CORE();
- #endif
-
- return found;
-}
-
-static err_t requestStationARP(struct netif* station, const ip4_addr_t* ip) {
- #ifdef HAS_IDF_3
- LOCK_TCPIP_CORE();
- #endif
- const err_t result = etharp_request(station, ip);
- #ifdef HAS_IDF_3
- UNLOCK_TCPIP_CORE();
- #endif
-
- return result;
-}
-
+#ifndef HAS_IDF_3
bool WiFiScan::readARP(IPAddress targ_ip) {
+ // Convert IPAddress to ip4_addr_t using IP4_ADDR
ip4_addr_t test_ip;
IP4_ADDR(&test_ip, targ_ip[0], targ_ip[1], targ_ip[2], targ_ip[3]);
- struct netif* netif_interface = getStationLwipNetif();
- if (netif_interface == nullptr)
- return false;
+ // Get the netif interface for STA mode
+ //void* netif = NULL;
+ //tcpip_adapter_get_netif(TCPIP_ADAPTER_IF_STA, &netif);
+ //struct netif* netif_interface = (struct netif*)netif;
+
+ const ip4_addr_t* ipaddr_ret = NULL;
+ struct eth_addr* eth_ret = NULL;
- return findStationARP(netif_interface, &test_ip);
+ // Use actual interface instead of NULL
+ if (etharp_find_addr(NULL, &test_ip, ð_ret, &ipaddr_ret) >= 0) {
+ return true;
+ }
+
+ return false;
}
bool WiFiScan::singleARP(IPAddress ip_addr) {
- struct netif* netif_interface = getStationLwipNetif();
- if (netif_interface == nullptr)
- return false;
+
+ #ifndef HAS_IDF_3
+ void* netif = NULL;
+ tcpip_adapter_get_netif(TCPIP_ADAPTER_IF_STA, &netif);
+ struct netif* netif_interface = (struct netif*)netif;
+ #else
+ struct netif* netif_interface = (struct netif*)esp_netif_get_netif_impl(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"));
+ //esp_netif_t* netif_interface = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF");
+ //struct netif* netif_interface = (struct netif*)netif;
+ //struct netif* netif_interface = esp_netif_get_netif_impl(*netif);
+ #endif
ip4_addr_t lwip_ip;
IP4_ADDR(&lwip_ip,
@@ -10622,7 +10510,7 @@ static err_t requestStationARP(struct netif* station, const ip4_addr_t* ip) {
ip_addr[2],
ip_addr[3]);
- requestStationARP(netif_interface, &lwip_ip);
+ etharp_request(netif_interface, &lwip_ip);
delay(250);
@@ -10636,14 +10524,20 @@ static err_t requestStationARP(struct netif* station, const ip4_addr_t* ip) {
String display_string = "";
String output_line = "";
- struct netif* netif_interface = getStationLwipNetif();
- if (netif_interface == nullptr)
- return;
+ #ifndef HAS_IDF_3
+ void* netif = NULL;
+ tcpip_adapter_get_netif(TCPIP_ADAPTER_IF_STA, &netif);
+ struct netif* netif_interface = (struct netif*)netif;
+ #else
+ struct netif* netif_interface = (struct netif*)esp_netif_get_netif_impl(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"));
+ //esp_netif_t* netif_interface = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF");
+ //struct netif* netif_interface = (struct netif*)netif;
+ //struct netif* netif_interface = esp_netif_get_netif_impl(*netif);
+ #endif
//this->arp_count = 0;
- if (this->current_scan_ip != IPAddress(0, 0, 0, 0) &&
- this->advanceScanIP() != IPAddress(0, 0, 0, 0)) {
+ if (this->current_scan_ip != IPAddress(0, 0, 0, 0)) {
ip4_addr_t lwip_ip;
IP4_ADDR(&lwip_ip,
this->current_scan_ip[0],
@@ -10651,10 +10545,12 @@ static err_t requestStationARP(struct netif* station, const ip4_addr_t* ip) {
this->current_scan_ip[2],
this->current_scan_ip[3]);
- requestStationARP(netif_interface, &lwip_ip);
+ etharp_request(netif_interface, &lwip_ip);
delay(100);
+ this->current_scan_ip = getNextIP(this->current_scan_ip, this->subnet);
+
this->arp_count++;
if (this->arp_count >= 10) {
@@ -10662,7 +10558,7 @@ static err_t requestStationARP(struct netif* station, const ip4_addr_t* ip) {
this->arp_count = 0;
- for (int i = 9; i >= 0; i--) {
+ for (int i = 10; i > 0; i--) {
IPAddress check_ip = getPrevIP(this->current_scan_ip, this->subnet, i);
display_string = "";
output_line = "";
@@ -10690,7 +10586,7 @@ static err_t requestStationARP(struct netif* station, const ip4_addr_t* ip) {
for (int i = this->arp_count; i > 0; i--) {
delay(250);
- IPAddress check_ip = getPrevIP(this->last_scan_ip, this->subnet, i - 1);
+ IPAddress check_ip = getPrevIP(this->current_scan_ip, this->subnet, i);
display_string = "";
output_line = "";
if (this->readARP(check_ip)) {
@@ -10718,21 +10614,29 @@ static err_t requestStationARP(struct netif* station, const ip4_addr_t* ip) {
}
}
}
-// GCOVR_EXCL_STOP
+#endif
void WiFiScan::pingScan(uint8_t scan_mode) {
+ String display_string = "";
String output_line = "";
if (scan_mode == WIFI_PING_SCAN) {
if (this->current_scan_ip != IPAddress(0, 0, 0, 0)) {
- this->advanceScanIP();
+ this->current_scan_ip = getNextIP(this->current_scan_ip, this->subnet);
// Check if IP is alive
- if ((this->current_scan_ip != IPAddress(0, 0, 0, 0)) &&
- this->isHostAlive(this->current_scan_ip)) {
+ if (this->isHostAlive(this->current_scan_ip)) {
output_line = this->current_scan_ip.toString();
+ display_string.concat(output_line);
+ uint8_t temp_len = display_string.length();
+ for (uint8_t i = 0; i < 40 - temp_len; i++)
+ {
+ display_string.concat(" ");
+ }
ipList->add(this->current_scan_ip);
- this->addNetworkScanDisplayResult(String("UP ") + output_line); // GCOVR_EXCL_LINE
+ #ifdef HAS_SCREEN
+ display_obj.display_buffer->add(display_string);
+ #endif
buffer_obj.append(output_line + "\n");
Serial.println(output_line);
}
@@ -10740,7 +10644,9 @@ void WiFiScan::pingScan(uint8_t scan_mode) {
else {
if (!this->scan_complete) {
this->scan_complete = true;
- this->finishNetworkScanDisplay("hosts up"); // GCOVR_EXCL_LINE
+ #ifdef HAS_SCREEN
+ display_obj.display_buffer->add("Scan complete");
+ #endif
}
}
}
@@ -10761,13 +10667,13 @@ void WiFiScan::pingScan(uint8_t scan_mode) {
else if (scan_mode == WIFI_SCAN_RDP)
targ_port = 3389;
- // GCOVR_EXCL_START -- service discovery requires a live lwIP station interface.
if (this->current_scan_ip != IPAddress(0, 0, 0, 0)) {
- this->advanceScanIP();
- if (this->current_scan_ip == IPAddress(0, 0, 0, 0)) {
- return;
- }
- if (this->singleARP(this->current_scan_ip)) {
+ this->current_scan_ip = getNextIP(this->current_scan_ip, this->subnet);
+ #ifndef HAS_IDF_3
+ if (this->singleARP(this->current_scan_ip)) {
+ #else
+ if (this->isHostAlive(this->current_scan_ip)) {
+ #endif
Serial.println(this->current_scan_ip);
this->portScan(scan_mode, targ_port);
}
@@ -10775,14 +10681,16 @@ void WiFiScan::pingScan(uint8_t scan_mode) {
else {
if (!this->scan_complete) {
this->scan_complete = true;
- this->finishNetworkScanDisplay("hosts open"); // GCOVR_EXCL_LINE
+ #ifdef HAS_SCREEN
+ display_obj.display_buffer->add("Scan complete");
+ #endif
}
}
- // GCOVR_EXCL_STOP
}
}
void WiFiScan::portScan(uint8_t scan_mode, uint16_t targ_port) {
+ String display_string = "";
if (scan_mode == WIFI_PORT_SCAN_ALL) {
if (this->current_scan_port < MAX_PORT) {
this->current_scan_port = getNextPort(this->current_scan_port);
@@ -10794,7 +10702,15 @@ void WiFiScan::portScan(uint8_t scan_mode, uint16_t targ_port) {
}
if (this->checkHostPort(this->current_scan_ip, this->current_scan_port, 100)) {
String output_line = this->current_scan_ip.toString() + ": " + (String)this->current_scan_port;
- this->addNetworkScanDisplayResult(String("OPEN ") + output_line); // GCOVR_EXCL_LINE
+ display_string.concat(output_line);
+ uint8_t temp_len = display_string.length();
+ for (uint8_t i = 0; i < 40 - temp_len; i++)
+ {
+ display_string.concat(" ");
+ }
+ #ifdef HAS_SCREEN
+ display_obj.display_buffer->add(display_string);
+ #endif
Serial.println(output_line);
buffer_obj.append(output_line + "\n");
}
@@ -10802,7 +10718,9 @@ void WiFiScan::portScan(uint8_t scan_mode, uint16_t targ_port) {
else {
if (!this->scan_complete) {
this->scan_complete = true;
- this->finishNetworkScanDisplay("ports open"); // GCOVR_EXCL_LINE
+ #ifdef HAS_SCREEN
+ display_obj.display_buffer->add("Scan complete");
+ #endif
}
}
}
@@ -10810,7 +10728,15 @@ void WiFiScan::portScan(uint8_t scan_mode, uint16_t targ_port) {
else {
if (this->checkHostPort(this->current_scan_ip, targ_port, 100)) {
String output_line = this->current_scan_ip.toString() + ": " + (String)targ_port;
- this->addNetworkScanDisplayResult(String("OPEN ") + output_line); // GCOVR_EXCL_LINE
+ display_string.concat(output_line);
+ uint8_t temp_len = display_string.length();
+ for (uint8_t i = 0; i < 40 - temp_len; i++)
+ {
+ display_string.concat(" ");
+ }
+ #ifdef HAS_SCREEN
+ display_obj.display_buffer->add(display_string);
+ #endif
Serial.println(output_line);
buffer_obj.append(output_line + "\n");
}
@@ -11733,7 +11659,9 @@ void WiFiScan::main(uint32_t currentTime)
this->pingScan();
}
else if (currentScanMode == WIFI_ARP_SCAN) {
- this->fullARP(); // GCOVR_EXCL_LINE -- requires a live lwIP station interface.
+ #ifndef HAS_IDF_3
+ this->fullARP();
+ #endif
}
else if (currentScanMode == WIFI_PORT_SCAN_ALL) {
this->portScan(WIFI_PORT_SCAN_ALL);
diff --git a/esp32_marauder/WiFiScan.h b/esp32_marauder/WiFiScan.h
index aac2198d6..ec2460fb2 100644
--- a/esp32_marauder/WiFiScan.h
+++ b/esp32_marauder/WiFiScan.h
@@ -32,13 +32,11 @@
#include "mbedtls/bignum.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/ecp.h"
-#include
-#include
-#include
-#include
+#ifndef HAS_IDF_3
+ #include
+ #include
+#endif
#ifdef HAS_IDF_3
- #include "esp_netif.h"
- #include "esp_netif_net_stack.h"
#include "esp_system.h"
#include "esp_mac.h"
#endif
@@ -711,17 +709,13 @@ class WiFiScan
void writeNetworkInfo();
void setupScanDisplayArea(uint16_t background, uint16_t color);
void updateTrackerUI();
- void showNetworkInfo(bool show_display = true);
- void resetNetworkScanDisplay(const String& target_line, const String& status_line);
- void addNetworkScanDisplayResult(const String& result_line);
- void finishNetworkScanDisplay(const String& result_label);
+ void showNetworkInfo();
void setNetworkInfo();
void fullARP();
bool readARP(IPAddress targ_ip);
bool singleARP(IPAddress ip_addr);
void pingScan(uint8_t scan_mode = WIFI_PING_SCAN);
void portScan(uint8_t scan_mode = WIFI_PORT_SCAN_ALL, uint16_t targ_port = 22);
- IPAddress advanceScanIP();
bool isHostAlive(IPAddress ip);
bool checkHostPort(IPAddress ip, uint16_t port, uint16_t timeout = 100);
String extractManufacturer(const uint8_t* payload);
@@ -936,10 +930,8 @@ class WiFiScan
IPAddress subnet;
IPAddress current_scan_ip;
- IPAddress last_scan_ip;
uint16_t current_scan_port = 1;
- uint16_t network_scan_result_count = 0;
String dst_mac = "ff:ff:ff:ff:ff:ff";
byte src_mac[6] = {};
diff --git a/esp32_marauder/configs.h b/esp32_marauder/configs.h
index 41444ed34..72512aef6 100644
--- a/esp32_marauder/configs.h
+++ b/esp32_marauder/configs.h
@@ -42,7 +42,7 @@
#define JSON_SETTING_SIZE 2048
-#define MARAUDER_VERSION "v1.15.1"
+#define MARAUDER_VERSION "v1.15.0"
#define GRAPH_REFRESH 100
diff --git a/esp32_marauder/utils.h b/esp32_marauder/utils.h
index 23d2a3a52..397ac1454 100644
--- a/esp32_marauder/utils.h
+++ b/esp32_marauder/utils.h
@@ -7,7 +7,6 @@
#include
#include "configs.h"
-#include "IPv4Range.h"
#include "MarauderMacAddress.h"
#include "esp_heap_caps.h"
@@ -194,45 +193,52 @@ inline void convertMacStringToUint8(const String& macStr, uint8_t macAddr[6]) {
}
-inline uint32_t ipAddressToUint32(const IPAddress& address) {
- return (static_cast(address[0]) << 24) |
- (static_cast(address[1]) << 16) |
- (static_cast(address[2]) << 8) |
- static_cast(address[3]);
-}
+inline IPAddress getNextIP(IPAddress currentIP, IPAddress subnetMask) {
+ // Convert IPAddress to uint32_t
+ uint32_t ipInt = (currentIP[0] << 24) | (currentIP[1] << 16) | (currentIP[2] << 8) | currentIP[3];
+ uint32_t maskInt = (subnetMask[0] << 24) | (subnetMask[1] << 16) | (subnetMask[2] << 8) | subnetMask[3];
+
+ uint32_t networkBase = ipInt & maskInt;
+ uint32_t broadcast = networkBase | ~maskInt;
+
+ uint32_t nextIP = ipInt + 1;
+
+ if (nextIP <= networkBase) {
+ nextIP = networkBase + 1;
+ }
+ if (nextIP >= broadcast) {
+ return IPAddress(0, 0, 0, 0); // no more IPs
+ }
-inline IPAddress uint32ToIPAddress(uint32_t address) {
return IPAddress(
- (address >> 24) & 0xFF,
- (address >> 16) & 0xFF,
- (address >> 8) & 0xFF,
- address & 0xFF
+ (nextIP >> 24) & 0xFF,
+ (nextIP >> 16) & 0xFF,
+ (nextIP >> 8) & 0xFF,
+ nextIP & 0xFF
);
}
-inline marauder::IPv4HostRange getIPHostRange(const IPAddress& address,
- const IPAddress& subnetMask) {
- return marauder::ipv4HostRange(ipAddressToUint32(address),
- ipAddressToUint32(subnetMask));
-}
+inline IPAddress getPrevIP(IPAddress currentIP, IPAddress subnetMask, uint16_t stepsBack) {
+ // Convert IPAddress to uint32_t
+ uint32_t ipInt = (currentIP[0] << 24) | (currentIP[1] << 16) | (currentIP[2] << 8) | currentIP[3];
+ uint32_t maskInt = (subnetMask[0] << 24) | (subnetMask[1] << 16) | (subnetMask[2] << 8) | subnetMask[3];
-inline IPAddress getNetworkIP(const IPAddress& address,
- const IPAddress& subnetMask) {
- return uint32ToIPAddress(getIPHostRange(address, subnetMask).network);
-}
+ uint32_t networkBase = ipInt & maskInt;
+ uint32_t broadcast = networkBase | ~maskInt;
-inline IPAddress getNextIP(const IPAddress& currentIP,
- const IPAddress& subnetMask) {
- const marauder::IPv4HostRange range = getIPHostRange(currentIP, subnetMask);
- return uint32ToIPAddress(
- marauder::nextIPv4Host(ipAddressToUint32(currentIP), range));
-}
+ uint32_t prevIP = ipInt - stepsBack;
+
+ // Ensure prevIP is not below the usable range
+ if (prevIP <= networkBase) {
+ return IPAddress(0, 0, 0, 0); // No more IPs
+ }
-inline IPAddress getPrevIP(const IPAddress& currentIP,
- const IPAddress& subnetMask, uint16_t stepsBack) {
- const marauder::IPv4HostRange range = getIPHostRange(currentIP, subnetMask);
- return uint32ToIPAddress(marauder::previousIPv4Host(
- ipAddressToUint32(currentIP), stepsBack, range));
+ return IPAddress(
+ (prevIP >> 24) & 0xFF,
+ (prevIP >> 16) & 0xFF,
+ (prevIP >> 8) & 0xFF,
+ prevIP & 0xFF
+ );
}
inline uint16_t getNextPort(uint16_t port) {
diff --git a/platformio.ini b/platformio.ini
index fe73d5450..5fdab083b 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -19,7 +19,6 @@ build_src_filter =
+
+
+
- +
build_flags =
-std=gnu++17
-Wall
diff --git a/test/test_ipv4_range/test_main.cpp b/test/test_ipv4_range/test_main.cpp
deleted file mode 100644
index f07f1be07..000000000
--- a/test/test_ipv4_range/test_main.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-#include
-
-#include "IPv4Range.h"
-
-namespace {
-
-constexpr uint32_t ip(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
- return (static_cast(a) << 24) |
- (static_cast(b) << 16) |
- (static_cast(c) << 8) | static_cast(d);
-}
-
-} // namespace
-
-void setUp() {}
-void tearDown() {}
-
-void test_slash_24_range_uses_network_and_broadcast_boundaries() {
- const auto range = marauder::ipv4HostRange(ip(192, 168, 1, 77),
- ip(255, 255, 255, 0));
- TEST_ASSERT_TRUE(range.valid);
- TEST_ASSERT_EQUAL_HEX32(ip(192, 168, 1, 0), range.network);
- TEST_ASSERT_EQUAL_HEX32(ip(192, 168, 1, 255), range.broadcast);
- TEST_ASSERT_EQUAL_HEX32(ip(192, 168, 1, 1), range.first);
- TEST_ASSERT_EQUAL_HEX32(ip(192, 168, 1, 254), range.last);
-}
-
-void test_slash_23_range_includes_hosts_below_gateway_octet() {
- const auto range = marauder::ipv4HostRange(ip(10, 0, 5, 1),
- ip(255, 255, 254, 0));
- TEST_ASSERT_EQUAL_HEX32(ip(10, 0, 4, 1), range.first);
- TEST_ASSERT_EQUAL_HEX32(ip(10, 0, 5, 254), range.last);
- TEST_ASSERT_EQUAL_HEX32(range.first,
- marauder::nextIPv4Host(range.network, range));
-}
-
-void test_gateway_near_broadcast_does_not_shorten_range() {
- const auto range = marauder::ipv4HostRange(ip(172, 16, 35, 126),
- ip(255, 255, 255, 192));
- TEST_ASSERT_EQUAL_HEX32(ip(172, 16, 35, 65), range.first);
- TEST_ASSERT_EQUAL_HEX32(ip(172, 16, 35, 126), range.last);
-}
-
-void test_iteration_stops_after_last_host() {
- const auto range = marauder::ipv4HostRange(ip(192, 168, 1, 10),
- ip(255, 255, 255, 252));
- TEST_ASSERT_EQUAL_HEX32(ip(192, 168, 1, 9),
- marauder::nextIPv4Host(range.network, range));
- TEST_ASSERT_EQUAL_HEX32(ip(192, 168, 1, 10),
- marauder::nextIPv4Host(range.first, range));
- TEST_ASSERT_EQUAL_HEX32(0, marauder::nextIPv4Host(range.last, range));
-}
-
-void test_previous_host_rejects_underflow_and_accepts_current_host() {
- const auto range = marauder::ipv4HostRange(ip(192, 168, 1, 10),
- ip(255, 255, 255, 0));
- TEST_ASSERT_EQUAL_HEX32(ip(192, 168, 1, 10),
- marauder::previousIPv4Host(ip(192, 168, 1, 10), 0,
- range));
- TEST_ASSERT_EQUAL_HEX32(ip(192, 168, 1, 1),
- marauder::previousIPv4Host(ip(192, 168, 1, 10), 9,
- range));
- TEST_ASSERT_EQUAL_HEX32(0,
- marauder::previousIPv4Host(ip(192, 168, 1, 10), 10,
- range));
-}
-
-void test_noncontiguous_and_hostless_masks_are_rejected() {
- TEST_ASSERT_FALSE(
- marauder::ipv4HostRange(ip(10, 0, 0, 1), ip(255, 0, 255, 0)).valid);
- TEST_ASSERT_FALSE(
- marauder::ipv4HostRange(ip(10, 0, 0, 1), ip(255, 255, 255, 254)).valid);
- TEST_ASSERT_FALSE(
- marauder::ipv4HostRange(ip(10, 0, 0, 1), ip(255, 255, 255, 255)).valid);
-}
-
-int main() {
- UNITY_BEGIN();
- RUN_TEST(test_slash_24_range_uses_network_and_broadcast_boundaries);
- RUN_TEST(test_slash_23_range_includes_hosts_below_gateway_octet);
- RUN_TEST(test_gateway_near_broadcast_does_not_shorten_range);
- RUN_TEST(test_iteration_stops_after_last_host);
- RUN_TEST(test_previous_host_rejects_underflow_and_accepts_current_host);
- RUN_TEST(test_noncontiguous_and_hostless_masks_are_rejected);
- return UNITY_END();
-}
diff --git a/tools/test_installer_manifest.py b/tools/test_installer_manifest.py
index 9fa191b5c..531f7e955 100644
--- a/tools/test_installer_manifest.py
+++ b/tools/test_installer_manifest.py
@@ -76,9 +76,6 @@ def test_registry_contains_unique_complete_build_targets(self) -> None:
)
self.assertEqual(registry_flags - private_flags, workflow_flags)
self.assertIn("MARAUDER_T_DONGLE_C5", workflow_flags)
- c5_devkit = next(board for board in boards if board["flag"] == "MARAUDER_C5")
- self.assertIn("FlashSize=8M", c5_devkit["fbqn"])
- self.assertIn("PartitionScheme=default_8MB", c5_devkit["fbqn"])
self.assertEqual(
len(registry_flags),
len(registry["targets"]),
From 082e69317fc5682ad3105fcf3256928fd5777c8c Mon Sep 17 00:00:00 2001
From: Just Call Me Koko <25190487+justcallmekoko@users.noreply.github.com>
Date: Sat, 22 Aug 2026 16:58:01 -0400
Subject: [PATCH 09/32] feat: back up SPIFFS content to SD
---
esp32_marauder/CommandLine.cpp | 19 ++++
esp32_marauder/CommandLine.h | 2 +
esp32_marauder/MenuFunctions.cpp | 34 ++++++-
esp32_marauder/SDInterface.cpp | 165 +++++++++++++++++++++++++++++++
esp32_marauder/SDInterface.h | 2 +
5 files changed, 218 insertions(+), 4 deletions(-)
diff --git a/esp32_marauder/CommandLine.cpp b/esp32_marauder/CommandLine.cpp
index 429829c46..ff80ee36e 100644
--- a/esp32_marauder/CommandLine.cpp
+++ b/esp32_marauder/CommandLine.cpp
@@ -231,6 +231,9 @@ void CommandLine::runCommand(String input) {
Serial.println(HELP_REBOOT_CMD);
Serial.println(HELP_UPDATE_CMD_A);
Serial.println(HELP_LS_CMD);
+ #ifdef HAS_SD
+ Serial.println(HELP_BACKUP_SPIFFS_CMD);
+ #endif
Serial.println(HELP_LED_CMD);
Serial.println(HELP_GPS_DATA_CMD);
Serial.println(HELP_GPS_CMD);
@@ -461,6 +464,22 @@ void CommandLine::runCommand(String input) {
sd_obj.listDir(cmd_args.get(1));
#endif
}
+ else if (cmd_args.get(0) == BACKUP_SPIFFS_CMD) {
+ #ifdef HAS_SD
+ size_t files_copied = 0;
+ size_t bytes_copied = 0;
+ String error;
+ if (sd_obj.backupSPIFFS(files_copied, bytes_copied, error)) {
+ Serial.println("SPIFFS backup complete: " + (String)files_copied +
+ " files, " + (String)bytes_copied + " bytes -> /spiffs");
+ }
+ else {
+ Serial.println("SPIFFS backup failed: " + error);
+ }
+ #else
+ Serial.println(F("SD Card NOT Supported"));
+ #endif
+ }
// Channel command
else if (cmd_args.get(0) == CH_CMD) {
diff --git a/esp32_marauder/CommandLine.h b/esp32_marauder/CommandLine.h
index 513851c03..dad05b49e 100644
--- a/esp32_marauder/CommandLine.h
+++ b/esp32_marauder/CommandLine.h
@@ -55,6 +55,7 @@ const char PROGMEM UPDATE_CMD[] = "update";
const char PROGMEM HELP_CMD[] = "help";
const char PROGMEM SETTINGS_CMD[] = "settings";
const char PROGMEM LS_CMD[] = "ls";
+const char PROGMEM BACKUP_SPIFFS_CMD[] = "backupspiffs";
const char PROGMEM LED_CMD[] = "led";
const char PROGMEM GPS_DATA_CMD[] = "gpsdata";
const char PROGMEM GPS_CMD[] = "gps";
@@ -133,6 +134,7 @@ const char PROGMEM HELP_REBOOT_CMD[] = "reboot";
const char PROGMEM HELP_UPDATE_CMD_A[] = "update -s/-w";
const char PROGMEM HELP_SETTINGS_CMD[] = "settings [-s enable/disable>]/[-r]";
const char PROGMEM HELP_LS_CMD[] = "ls ";
+const char PROGMEM HELP_BACKUP_SPIFFS_CMD[] = "backupspiffs - copy SPIFFS to /spiffs on SD";
const char PROGMEM HELP_LED_CMD[] = "led -s /-p ";
const char PROGMEM HELP_GPS_DATA_CMD[] = "gpsdata";
const char PROGMEM HELP_GPS_CMD[] = "gps [-t] [-g] \r\n [-n] \r\n [-b = use BD vs GB for beidou]";
diff --git a/esp32_marauder/MenuFunctions.cpp b/esp32_marauder/MenuFunctions.cpp
index 9a0d830fe..86a822e94 100644
--- a/esp32_marauder/MenuFunctions.cpp
+++ b/esp32_marauder/MenuFunctions.cpp
@@ -3474,7 +3474,7 @@ void MenuFunctions::RunSetup()
sdDeleteMenu.parentMenu = &deviceMenu;
- this->addNodes(&deviceMenu, "Update Firmware", TFTORANGE, SD_UPDATE, [this]() {
+ this->addNodes(&deviceMenu, "Update Firmware", TFTORANGE, SD_UPDATE, [this]() {
display_obj.clearScreen();
display_obj.tft.setTextWrap(false);
display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
@@ -3484,9 +3484,35 @@ void MenuFunctions::RunSetup()
// Clear menu and lists
this->buildSDFileMenu(true);
- this->changeMenu(&sdDeleteMenu, true);
- });
- }
+ this->changeMenu(&sdDeleteMenu, true);
+ });
+
+ this->addNodes(&deviceMenu, "Backup SPIFFS", TFTGREEN, SD_UPDATE, [this]() {
+ display_obj.clearScreen();
+ display_obj.tft.setTextWrap(true);
+ display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
+ display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
+ display_obj.tft.println("Backing up SPIFFS...");
+
+ size_t files_copied = 0;
+ size_t bytes_copied = 0;
+ String error;
+ if (sd_obj.backupSPIFFS(files_copied, bytes_copied, error)) {
+ display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK);
+ display_obj.tft.println("Backup complete");
+ display_obj.tft.println((String)files_copied + " files");
+ display_obj.tft.println("SD:/spiffs");
+ }
+ else {
+ display_obj.tft.setTextColor(TFT_RED, TFT_BLACK);
+ display_obj.tft.println("Backup failed");
+ display_obj.tft.println(error);
+ }
+
+ delay(2500);
+ this->changeMenu(&deviceMenu, true);
+ });
+ }
#endif
this->addNodes(&deviceMenu, "Save/Load Files", TFTCYAN, SD_UPDATE, [this]() {
diff --git a/esp32_marauder/SDInterface.cpp b/esp32_marauder/SDInterface.cpp
index 0287c1914..01e425c2a 100644
--- a/esp32_marauder/SDInterface.cpp
+++ b/esp32_marauder/SDInterface.cpp
@@ -1,6 +1,130 @@
#include "SDInterface.h"
#include "lang_var.h"
+namespace {
+ bool ensureDirectory(fs::FS& fs, const String& path) {
+ if (path.length() == 0 || path == "/" || fs.exists(path))
+ return true;
+
+ int slash = path.lastIndexOf('/');
+ if (slash > 0 && !ensureDirectory(fs, path.substring(0, slash)))
+ return false;
+
+ return fs.mkdir(path);
+ }
+
+ bool removeTree(fs::FS& fs, const String& path) {
+ if (!fs.exists(path))
+ return true;
+
+ File node = fs.open(path);
+ if (!node)
+ return false;
+
+ if (!node.isDirectory()) {
+ node.close();
+ return fs.remove(path);
+ }
+
+ File child = node.openNextFile();
+ while (child) {
+ String child_path = child.path();
+ child.close();
+ if (!removeTree(fs, child_path)) {
+ node.close();
+ return false;
+ }
+ child = node.openNextFile();
+ }
+
+ node.close();
+ return fs.rmdir(path);
+ }
+
+ bool copyTree(
+ fs::FS& source,
+ const String& source_path,
+ fs::FS& destination,
+ const String& destination_path,
+ size_t& files_copied,
+ size_t& bytes_copied,
+ String& error
+ ) {
+ File source_node = source.open(source_path);
+ if (!source_node) {
+ error = "Could not open SPIFFS path " + source_path;
+ return false;
+ }
+
+ if (!source_node.isDirectory()) {
+ int slash = destination_path.lastIndexOf('/');
+ if (slash > 0 && !ensureDirectory(destination, destination_path.substring(0, slash))) {
+ source_node.close();
+ error = "Could not create SD backup directory";
+ return false;
+ }
+
+ File destination_file = destination.open(destination_path, FILE_WRITE);
+ if (!destination_file) {
+ source_node.close();
+ error = "Could not create " + destination_path;
+ return false;
+ }
+
+ uint8_t buffer[512];
+ while (source_node.available()) {
+ size_t bytes_read = source_node.read(buffer, sizeof(buffer));
+ if (bytes_read == 0 || destination_file.write(buffer, bytes_read) != bytes_read) {
+ source_node.close();
+ destination_file.close();
+ error = "Failed while copying " + source_path;
+ return false;
+ }
+ bytes_copied += bytes_read;
+ }
+
+ source_node.close();
+ destination_file.close();
+ files_copied++;
+ return true;
+ }
+
+ if (!ensureDirectory(destination, destination_path)) {
+ source_node.close();
+ error = "Could not create " + destination_path;
+ return false;
+ }
+
+ File child = source_node.openNextFile();
+ while (child) {
+ String child_source_path = child.path();
+ String child_name = child_source_path;
+ if (child_name.startsWith(source_path))
+ child_name.remove(0, source_path.length());
+ while (child_name.startsWith("/"))
+ child_name.remove(0, 1);
+ child.close();
+
+ if (!copyTree(
+ source,
+ child_source_path,
+ destination,
+ destination_path + "/" + child_name,
+ files_copied,
+ bytes_copied,
+ error
+ )) {
+ source_node.close();
+ return false;
+ }
+ child = source_node.openNextFile();
+ }
+
+ source_node.close();
+ return true;
+ }
+}
+
#ifdef HAS_C5_SD
SDInterface::SDInterface(SPIClass* spi, int cs)
: _spi(spi), _cs(cs) {}
@@ -107,6 +231,47 @@ bool SDInterface::removeFile(String file_path) {
return false;
}
+bool SDInterface::backupSPIFFS(size_t& files_copied, size_t& bytes_copied, String& error) {
+ files_copied = 0;
+ bytes_copied = 0;
+ error = "";
+
+ if (!this->supported) {
+ error = "SD card not detected";
+ return false;
+ }
+
+ const String backup_path = "/spiffs";
+ const String staging_path = "/spiffs.tmp";
+ const String previous_path = "/spiffs.previous";
+
+ if (!removeTree(SD, staging_path) || !removeTree(SD, previous_path)) {
+ error = "Could not clear old SPIFFS backup data";
+ return false;
+ }
+
+ if (!copyTree(SPIFFS, "/", SD, staging_path, files_copied, bytes_copied, error)) {
+ removeTree(SD, staging_path);
+ return false;
+ }
+
+ if (SD.exists(backup_path) && !SD.rename(backup_path, previous_path)) {
+ removeTree(SD, staging_path);
+ error = "Could not rotate existing SPIFFS backup";
+ return false;
+ }
+
+ if (!SD.rename(staging_path, backup_path)) {
+ if (SD.exists(previous_path))
+ SD.rename(previous_path, backup_path);
+ error = "Could not activate new SPIFFS backup";
+ return false;
+ }
+
+ removeTree(SD, previous_path);
+ return true;
+}
+
void SDInterface::listDirToLinkedList(LinkedList* file_names, String str_dir, String ext) {
if (this->supported) {
File dir = SD.open(str_dir);
diff --git a/esp32_marauder/SDInterface.h b/esp32_marauder/SDInterface.h
index 0d3c8cb70..76a5a6a48 100644
--- a/esp32_marauder/SDInterface.h
+++ b/esp32_marauder/SDInterface.h
@@ -10,6 +10,7 @@
#include "FS.h"
#endif
#include "SD.h"
+#include "SPIFFS.h"
#ifdef HAS_C5_SD
#include "SPI.h"
#endif
@@ -68,6 +69,7 @@ class SDInterface {
void runUpdate(String file_name = "");
void performUpdate(Stream &updateSource, size_t updateSize);
bool removeFile(String file_path);
+ bool backupSPIFFS(size_t& files_copied, size_t& bytes_copied, String& error);
};
#endif
From 53ca4ea2467cfcbf0d50cf770f85762e1d8c3e4c Mon Sep 17 00:00:00 2001
From: Just Call Me Koko <25190487+justcallmekoko@users.noreply.github.com>
Date: Sat, 22 Aug 2026 17:05:40 -0400
Subject: [PATCH 10/32] test: exclude hardware-only backup paths
---
esp32_marauder/CommandLine.cpp | 4 ++++
esp32_marauder/SDInterface.cpp | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/esp32_marauder/CommandLine.cpp b/esp32_marauder/CommandLine.cpp
index ff80ee36e..0bbc6b1a4 100644
--- a/esp32_marauder/CommandLine.cpp
+++ b/esp32_marauder/CommandLine.cpp
@@ -231,9 +231,11 @@ void CommandLine::runCommand(String input) {
Serial.println(HELP_REBOOT_CMD);
Serial.println(HELP_UPDATE_CMD_A);
Serial.println(HELP_LS_CMD);
+ // GCOVR_EXCL_START -- hardware-only command help entry.
#ifdef HAS_SD
Serial.println(HELP_BACKUP_SPIFFS_CMD);
#endif
+ // GCOVR_EXCL_STOP
Serial.println(HELP_LED_CMD);
Serial.println(HELP_GPS_DATA_CMD);
Serial.println(HELP_GPS_CMD);
@@ -464,6 +466,7 @@ void CommandLine::runCommand(String input) {
sd_obj.listDir(cmd_args.get(1));
#endif
}
+ // GCOVR_EXCL_START -- requires mounted SPIFFS and SD filesystems.
else if (cmd_args.get(0) == BACKUP_SPIFFS_CMD) {
#ifdef HAS_SD
size_t files_copied = 0;
@@ -480,6 +483,7 @@ void CommandLine::runCommand(String input) {
Serial.println(F("SD Card NOT Supported"));
#endif
}
+ // GCOVR_EXCL_STOP
// Channel command
else if (cmd_args.get(0) == CH_CMD) {
diff --git a/esp32_marauder/SDInterface.cpp b/esp32_marauder/SDInterface.cpp
index 01e425c2a..3d977be6f 100644
--- a/esp32_marauder/SDInterface.cpp
+++ b/esp32_marauder/SDInterface.cpp
@@ -1,6 +1,7 @@
#include "SDInterface.h"
#include "lang_var.h"
+// GCOVR_EXCL_START -- requires mounted SPIFFS and SD filesystems.
namespace {
bool ensureDirectory(fs::FS& fs, const String& path) {
if (path.length() == 0 || path == "/" || fs.exists(path))
@@ -124,6 +125,7 @@ namespace {
return true;
}
}
+// GCOVR_EXCL_STOP
#ifdef HAS_C5_SD
SDInterface::SDInterface(SPIClass* spi, int cs)
@@ -231,6 +233,7 @@ bool SDInterface::removeFile(String file_path) {
return false;
}
+// GCOVR_EXCL_START -- requires mounted SPIFFS and SD filesystems.
bool SDInterface::backupSPIFFS(size_t& files_copied, size_t& bytes_copied, String& error) {
files_copied = 0;
bytes_copied = 0;
@@ -271,6 +274,7 @@ bool SDInterface::backupSPIFFS(size_t& files_copied, size_t& bytes_copied, Strin
removeTree(SD, previous_path);
return true;
}
+// GCOVR_EXCL_STOP
void SDInterface::listDirToLinkedList(LinkedList* file_names, String str_dir, String ext) {
if (this->supported) {
From 94c93b6e8592a1594b7322f798d093e373ac8c76 Mon Sep 17 00:00:00 2001
From: Just Call Me Koko <25190487+justcallmekoko@users.noreply.github.com>
Date: Sat, 22 Aug 2026 17:41:46 -0400
Subject: [PATCH 11/32] Add SPIFFS restore from SD backup
---
esp32_marauder/CommandLine.cpp | 20 ++++++++
esp32_marauder/CommandLine.h | 2 +
esp32_marauder/MenuFunctions.cpp | 29 +++++++++++
esp32_marauder/SDInterface.cpp | 87 ++++++++++++++++++++++++++++++--
esp32_marauder/SDInterface.h | 1 +
5 files changed, 136 insertions(+), 3 deletions(-)
diff --git a/esp32_marauder/CommandLine.cpp b/esp32_marauder/CommandLine.cpp
index 0bbc6b1a4..294eb0793 100644
--- a/esp32_marauder/CommandLine.cpp
+++ b/esp32_marauder/CommandLine.cpp
@@ -234,6 +234,7 @@ void CommandLine::runCommand(String input) {
// GCOVR_EXCL_START -- hardware-only command help entry.
#ifdef HAS_SD
Serial.println(HELP_BACKUP_SPIFFS_CMD);
+ Serial.println(HELP_RESTORE_SPIFFS_CMD);
#endif
// GCOVR_EXCL_STOP
Serial.println(HELP_LED_CMD);
@@ -483,6 +484,25 @@ void CommandLine::runCommand(String input) {
Serial.println(F("SD Card NOT Supported"));
#endif
}
+ else if (cmd_args.get(0) == RESTORE_SPIFFS_CMD) {
+ #ifdef HAS_SD
+ size_t files_copied = 0;
+ size_t bytes_copied = 0;
+ String error;
+ if (sd_obj.restoreSPIFFS(files_copied, bytes_copied, error)) {
+ Serial.println("SPIFFS restore complete: " + (String)files_copied +
+ " files, " + (String)bytes_copied + " bytes");
+ Serial.println(F("Restarting to load restored content..."));
+ delay(1000);
+ ESP.restart();
+ }
+ else {
+ Serial.println("SPIFFS restore failed: " + error);
+ }
+ #else
+ Serial.println(F("SD Card NOT Supported"));
+ #endif
+ }
// GCOVR_EXCL_STOP
// Channel command
diff --git a/esp32_marauder/CommandLine.h b/esp32_marauder/CommandLine.h
index dad05b49e..1b2857073 100644
--- a/esp32_marauder/CommandLine.h
+++ b/esp32_marauder/CommandLine.h
@@ -56,6 +56,7 @@ const char PROGMEM HELP_CMD[] = "help";
const char PROGMEM SETTINGS_CMD[] = "settings";
const char PROGMEM LS_CMD[] = "ls";
const char PROGMEM BACKUP_SPIFFS_CMD[] = "backupspiffs";
+const char PROGMEM RESTORE_SPIFFS_CMD[] = "restorespiffs";
const char PROGMEM LED_CMD[] = "led";
const char PROGMEM GPS_DATA_CMD[] = "gpsdata";
const char PROGMEM GPS_CMD[] = "gps";
@@ -135,6 +136,7 @@ const char PROGMEM HELP_UPDATE_CMD_A[] = "update -s/-w";
const char PROGMEM HELP_SETTINGS_CMD[] = "settings [-s enable/disable>]/[-r]";
const char PROGMEM HELP_LS_CMD[] = "ls ";
const char PROGMEM HELP_BACKUP_SPIFFS_CMD[] = "backupspiffs - copy SPIFFS to /spiffs on SD";
+const char PROGMEM HELP_RESTORE_SPIFFS_CMD[] = "restorespiffs - restore SPIFFS from /spiffs on SD";
const char PROGMEM HELP_LED_CMD[] = "led -s /-p ";
const char PROGMEM HELP_GPS_DATA_CMD[] = "gpsdata";
const char PROGMEM HELP_GPS_CMD[] = "gps [-t] [-g] \r\n [-n] \r\n [-b = use BD vs GB for beidou]";
diff --git a/esp32_marauder/MenuFunctions.cpp b/esp32_marauder/MenuFunctions.cpp
index 86a822e94..06fc79ef8 100644
--- a/esp32_marauder/MenuFunctions.cpp
+++ b/esp32_marauder/MenuFunctions.cpp
@@ -3487,6 +3487,7 @@ void MenuFunctions::RunSetup()
this->changeMenu(&sdDeleteMenu, true);
});
+ // GCOVR_EXCL_START -- requires mounted SPIFFS, SD, and a hardware display.
this->addNodes(&deviceMenu, "Backup SPIFFS", TFTGREEN, SD_UPDATE, [this]() {
display_obj.clearScreen();
display_obj.tft.setTextWrap(true);
@@ -3512,6 +3513,34 @@ void MenuFunctions::RunSetup()
delay(2500);
this->changeMenu(&deviceMenu, true);
});
+
+ this->addNodes(&deviceMenu, "Restore SPIFFS", TFTORANGE, SD_UPDATE, [this]() {
+ display_obj.clearScreen();
+ display_obj.tft.setTextWrap(true);
+ display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3);
+ display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
+ display_obj.tft.println("Restoring SPIFFS...");
+
+ size_t files_copied = 0;
+ size_t bytes_copied = 0;
+ String error;
+ if (sd_obj.restoreSPIFFS(files_copied, bytes_copied, error)) {
+ display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK);
+ display_obj.tft.println("Restore complete");
+ display_obj.tft.println((String)files_copied + " files");
+ display_obj.tft.println("Restarting...");
+ delay(1500);
+ ESP.restart();
+ }
+ else {
+ display_obj.tft.setTextColor(TFT_RED, TFT_BLACK);
+ display_obj.tft.println("Restore failed");
+ display_obj.tft.println(error);
+ delay(3000);
+ this->changeMenu(&deviceMenu, true);
+ }
+ });
+ // GCOVR_EXCL_STOP
}
#endif
diff --git a/esp32_marauder/SDInterface.cpp b/esp32_marauder/SDInterface.cpp
index 3d977be6f..d35c94dff 100644
--- a/esp32_marauder/SDInterface.cpp
+++ b/esp32_marauder/SDInterface.cpp
@@ -42,6 +42,32 @@ namespace {
return fs.rmdir(path);
}
+ bool clearDirectoryContents(fs::FS& fs, const String& path) {
+ File directory = fs.open(path);
+ if (!directory || !directory.isDirectory()) {
+ directory.close();
+ return false;
+ }
+
+ File child = directory.openNextFile();
+ while (child) {
+ String child_path = child.path();
+ child.close();
+ if (!removeTree(fs, child_path)) {
+ directory.close();
+ return false;
+ }
+ child = directory.openNextFile();
+ }
+
+ directory.close();
+ return true;
+ }
+
+ String joinPath(const String& base, const String& child) {
+ return base == "/" ? "/" + child : base + "/" + child;
+ }
+
bool copyTree(
fs::FS& source,
const String& source_path,
@@ -53,7 +79,7 @@ namespace {
) {
File source_node = source.open(source_path);
if (!source_node) {
- error = "Could not open SPIFFS path " + source_path;
+ error = "Could not open source path " + source_path;
return false;
}
@@ -61,7 +87,7 @@ namespace {
int slash = destination_path.lastIndexOf('/');
if (slash > 0 && !ensureDirectory(destination, destination_path.substring(0, slash))) {
source_node.close();
- error = "Could not create SD backup directory";
+ error = "Could not create destination directory";
return false;
}
@@ -110,7 +136,7 @@ namespace {
source,
child_source_path,
destination,
- destination_path + "/" + child_name,
+ joinPath(destination_path, child_name),
files_copied,
bytes_copied,
error
@@ -274,6 +300,61 @@ bool SDInterface::backupSPIFFS(size_t& files_copied, size_t& bytes_copied, Strin
removeTree(SD, previous_path);
return true;
}
+
+bool SDInterface::restoreSPIFFS(size_t& files_copied, size_t& bytes_copied, String& error) {
+ files_copied = 0;
+ bytes_copied = 0;
+ error = "";
+
+ if (!this->supported) {
+ error = "SD card not detected";
+ return false;
+ }
+
+ const String backup_path = "/spiffs";
+ const String rollback_path = "/spiffs.restore-rollback";
+ File backup = SD.open(backup_path);
+ bool valid_backup = backup && backup.isDirectory();
+ backup.close();
+ if (!valid_backup) {
+ error = "SD:/spiffs backup not found";
+ return false;
+ }
+
+ if (!removeTree(SD, rollback_path)) {
+ error = "Could not clear old restore rollback";
+ return false;
+ }
+
+ size_t rollback_files = 0;
+ size_t rollback_bytes = 0;
+ String rollback_error;
+ if (!copyTree(SPIFFS, "/", SD, rollback_path, rollback_files, rollback_bytes, rollback_error)) {
+ removeTree(SD, rollback_path);
+ error = "Could not preserve current SPIFFS: " + rollback_error;
+ return false;
+ }
+
+ bool cleared = clearDirectoryContents(SPIFFS, "/");
+ if (cleared && copyTree(SD, backup_path, SPIFFS, "/", files_copied, bytes_copied, error)) {
+ removeTree(SD, rollback_path);
+ return true;
+ }
+
+ String restore_error = cleared ? error : "Could not clear SPIFFS before restore";
+ clearDirectoryContents(SPIFFS, "/");
+ size_t recovered_files = 0;
+ size_t recovered_bytes = 0;
+ String recovery_error;
+ if (copyTree(SD, rollback_path, SPIFFS, "/", recovered_files, recovered_bytes, recovery_error)) {
+ removeTree(SD, rollback_path);
+ error = "Restore failed; original SPIFFS recovered: " + restore_error;
+ }
+ else {
+ error = "Restore and rollback failed: " + restore_error + "; " + recovery_error;
+ }
+ return false;
+}
// GCOVR_EXCL_STOP
void SDInterface::listDirToLinkedList(LinkedList* file_names, String str_dir, String ext) {
diff --git a/esp32_marauder/SDInterface.h b/esp32_marauder/SDInterface.h
index 76a5a6a48..1eafd62f5 100644
--- a/esp32_marauder/SDInterface.h
+++ b/esp32_marauder/SDInterface.h
@@ -70,6 +70,7 @@ class SDInterface {
void performUpdate(Stream &updateSource, size_t updateSize);
bool removeFile(String file_path);
bool backupSPIFFS(size_t& files_copied, size_t& bytes_copied, String& error);
+ bool restoreSPIFFS(size_t& files_copied, size_t& bytes_copied, String& error);
};
#endif
From ccb255eb11d32d00a119b67918d7fc22f9de8836 Mon Sep 17 00:00:00 2001
From: Just Call Me Koko <25190487+justcallmekoko@users.noreply.github.com>
Date: Sat, 22 Aug 2026 21:06:28 -0400
Subject: [PATCH 12/32] Add machine protocol for SPIFFS migration
---
esp32_marauder/CommandLine.cpp | 187 ++++++++++++++++++++++++--
esp32_marauder/CommandLine.h | 8 +-
esp32_marauder/SDInterface.cpp | 56 ++++++++
esp32_marauder/SDInterface.h | 1 +
tools/test_spiffs_machine_protocol.py | 42 ++++++
5 files changed, 283 insertions(+), 11 deletions(-)
create mode 100644 tools/test_spiffs_machine_protocol.py
diff --git a/esp32_marauder/CommandLine.cpp b/esp32_marauder/CommandLine.cpp
index 294eb0793..8784d6f61 100644
--- a/esp32_marauder/CommandLine.cpp
+++ b/esp32_marauder/CommandLine.cpp
@@ -1,5 +1,79 @@
#include "CommandLine.h"
+// GCOVR_EXCL_START -- serial protocol output depends on Arduino Serial.
+namespace {
+ const int MARAUDER_PROTOCOL_VERSION = 1;
+ const char* MARAUDER_PROTOCOL_PREFIX = "@MARAUDER:";
+
+ String jsonEscape(const String& value) {
+ String escaped;
+ for (size_t i = 0; i < value.length(); i++) {
+ char c = value.charAt(i);
+ if (c == '\\' || c == '"') {
+ escaped += '\\';
+ escaped += c;
+ }
+ else if (c == '\n')
+ escaped += "\\n";
+ else if (c == '\r')
+ escaped += "\\r";
+ else if ((uint8_t)c >= 0x20)
+ escaped += c;
+ }
+ return escaped;
+ }
+
+ bool validTransactionId(const String& transaction_id) {
+ if (transaction_id.length() == 0 || transaction_id.length() > 40)
+ return false;
+
+ for (size_t i = 0; i < transaction_id.length(); i++) {
+ char c = transaction_id.charAt(i);
+ if (!isalnum((unsigned char)c) && c != '-' && c != '_' && c != '.')
+ return false;
+ }
+ return true;
+ }
+
+ void machineResult(
+ const String& transaction_id,
+ const String& command,
+ const String& status,
+ const String& code,
+ size_t files = 0,
+ size_t bytes = 0,
+ bool rebooting = false
+ ) {
+ Serial.print(MARAUDER_PROTOCOL_PREFIX);
+ Serial.print("{\"protocol\":");
+ Serial.print(MARAUDER_PROTOCOL_VERSION);
+ Serial.print(",\"tx\":\"");
+ Serial.print(jsonEscape(transaction_id));
+ Serial.print("\",\"command\":\"");
+ Serial.print(command);
+ Serial.print("\",\"status\":\"");
+ Serial.print(status);
+ Serial.print("\",\"code\":\"");
+ Serial.print(code);
+ Serial.print("\",\"files\":");
+ Serial.print(files);
+ Serial.print(",\"bytes\":");
+ Serial.print(bytes);
+ Serial.print(",\"rebooting\":");
+ Serial.print(rebooting ? "true" : "false");
+ Serial.println("}");
+ }
+
+ String storageErrorCode(const String& error, const String& fallback) {
+ if (error == "SD card not detected")
+ return "SD_NOT_READY";
+ if (error == "SD:/spiffs backup not found")
+ return "BACKUP_NOT_FOUND";
+ return fallback;
+ }
+}
+// GCOVR_EXCL_STOP
+
// Brightness functions defined in esp32_marauder.ino
#ifndef HAS_MINI_SCREEN
extern void brightnessCycle();
@@ -231,9 +305,11 @@ void CommandLine::runCommand(String input) {
Serial.println(HELP_REBOOT_CMD);
Serial.println(HELP_UPDATE_CMD_A);
Serial.println(HELP_LS_CMD);
+ Serial.println(HELP_PROTOCOL_INFO_CMD);
// GCOVR_EXCL_START -- hardware-only command help entry.
#ifdef HAS_SD
Serial.println(HELP_BACKUP_SPIFFS_CMD);
+ Serial.println(HELP_BACKUP_STATUS_CMD);
Serial.println(HELP_RESTORE_SPIFFS_CMD);
#endif
// GCOVR_EXCL_STOP
@@ -468,39 +544,132 @@ void CommandLine::runCommand(String input) {
#endif
}
// GCOVR_EXCL_START -- requires mounted SPIFFS and SD filesystems.
+ else if (cmd_args.get(0) == PROTOCOL_INFO_CMD) {
+ int machine_arg = this->argSearch(&cmd_args, "--machine");
+ String transaction_id = machine_arg >= 0 && machine_arg + 1 < cmd_args.size()
+ ? cmd_args.get(machine_arg + 1) : "";
+ if (machine_arg >= 0 && !validTransactionId(transaction_id))
+ machineResult(transaction_id, PROTOCOL_INFO_CMD, "error", "INVALID_TRANSACTION");
+ else if (machine_arg >= 0) {
+ Serial.print(MARAUDER_PROTOCOL_PREFIX);
+ Serial.print("{\"protocol\":1,\"tx\":\"");
+ Serial.print(jsonEscape(transaction_id));
+ Serial.print("\",\"command\":\"protocolinfo\",\"status\":\"success\",\"code\":\"OK\",\"firmware\":\"");
+ Serial.print(jsonEscape(version_number));
+ Serial.print("\",\"board\":\"");
+ Serial.print(jsonEscape(board_target));
+ #ifdef HAS_SD
+ Serial.println("\",\"capabilities\":[\"spiffs-backup\",\"spiffs-backup-status\",\"spiffs-restore\"],\"backupPath\":\"/spiffs\"}");
+ #else
+ Serial.println("\",\"capabilities\":[]}");
+ #endif
+ }
+ else
+ Serial.println(F("Marauder automation protocol v1: spiffs-backup, spiffs-backup-status, spiffs-restore"));
+ }
else if (cmd_args.get(0) == BACKUP_SPIFFS_CMD) {
+ int machine_arg = this->argSearch(&cmd_args, "--machine");
+ String transaction_id = machine_arg >= 0 && machine_arg + 1 < cmd_args.size()
+ ? cmd_args.get(machine_arg + 1) : "";
+ bool machine = machine_arg >= 0;
+ if (machine && !validTransactionId(transaction_id)) {
+ machineResult(transaction_id, BACKUP_SPIFFS_CMD, "error", "INVALID_TRANSACTION");
+ return;
+ }
#ifdef HAS_SD
size_t files_copied = 0;
size_t bytes_copied = 0;
String error;
+ if (machine)
+ machineResult(transaction_id, BACKUP_SPIFFS_CMD, "started", "OK");
if (sd_obj.backupSPIFFS(files_copied, bytes_copied, error)) {
- Serial.println("SPIFFS backup complete: " + (String)files_copied +
- " files, " + (String)bytes_copied + " bytes -> /spiffs");
+ if (machine)
+ machineResult(transaction_id, BACKUP_SPIFFS_CMD, "success", "OK", files_copied, bytes_copied);
+ else
+ Serial.println("SPIFFS backup complete: " + (String)files_copied +
+ " files, " + (String)bytes_copied + " bytes -> /spiffs");
}
else {
- Serial.println("SPIFFS backup failed: " + error);
+ if (machine)
+ machineResult(transaction_id, BACKUP_SPIFFS_CMD, "error", storageErrorCode(error, "BACKUP_FAILED"));
+ else
+ Serial.println("SPIFFS backup failed: " + error);
}
#else
- Serial.println(F("SD Card NOT Supported"));
+ if (machine)
+ machineResult(transaction_id, BACKUP_SPIFFS_CMD, "error", "SD_NOT_SUPPORTED");
+ else
+ Serial.println(F("SD Card NOT Supported"));
+ #endif
+ }
+ else if (cmd_args.get(0) == BACKUP_STATUS_CMD) {
+ int machine_arg = this->argSearch(&cmd_args, "--machine");
+ String transaction_id = machine_arg >= 0 && machine_arg + 1 < cmd_args.size()
+ ? cmd_args.get(machine_arg + 1) : "";
+ bool machine = machine_arg >= 0;
+ if (machine && !validTransactionId(transaction_id)) {
+ machineResult(transaction_id, BACKUP_STATUS_CMD, "error", "INVALID_TRANSACTION");
+ return;
+ }
+ #ifdef HAS_SD
+ size_t files_found = 0;
+ size_t bytes_found = 0;
+ String error;
+ if (sd_obj.inspectSPIFFSBackup(files_found, bytes_found, error)) {
+ if (machine)
+ machineResult(transaction_id, BACKUP_STATUS_CMD, "success", "OK", files_found, bytes_found);
+ else
+ Serial.println("SPIFFS backup ready: " + (String)files_found +
+ " files, " + (String)bytes_found + " bytes in /spiffs");
+ }
+ else if (machine)
+ machineResult(transaction_id, BACKUP_STATUS_CMD, "error", storageErrorCode(error, "BACKUP_INSPECTION_FAILED"));
+ else
+ Serial.println("SPIFFS backup unavailable: " + error);
+ #else
+ if (machine)
+ machineResult(transaction_id, BACKUP_STATUS_CMD, "error", "SD_NOT_SUPPORTED");
+ else
+ Serial.println(F("SD Card NOT Supported"));
#endif
}
else if (cmd_args.get(0) == RESTORE_SPIFFS_CMD) {
+ int machine_arg = this->argSearch(&cmd_args, "--machine");
+ String transaction_id = machine_arg >= 0 && machine_arg + 1 < cmd_args.size()
+ ? cmd_args.get(machine_arg + 1) : "";
+ bool machine = machine_arg >= 0;
+ if (machine && !validTransactionId(transaction_id)) {
+ machineResult(transaction_id, RESTORE_SPIFFS_CMD, "error", "INVALID_TRANSACTION");
+ return;
+ }
#ifdef HAS_SD
size_t files_copied = 0;
size_t bytes_copied = 0;
String error;
+ if (machine)
+ machineResult(transaction_id, RESTORE_SPIFFS_CMD, "started", "OK");
if (sd_obj.restoreSPIFFS(files_copied, bytes_copied, error)) {
- Serial.println("SPIFFS restore complete: " + (String)files_copied +
- " files, " + (String)bytes_copied + " bytes");
- Serial.println(F("Restarting to load restored content..."));
+ if (machine)
+ machineResult(transaction_id, RESTORE_SPIFFS_CMD, "success", "OK", files_copied, bytes_copied, true);
+ else {
+ Serial.println("SPIFFS restore complete: " + (String)files_copied +
+ " files, " + (String)bytes_copied + " bytes");
+ Serial.println(F("Restarting to load restored content..."));
+ }
delay(1000);
ESP.restart();
}
else {
- Serial.println("SPIFFS restore failed: " + error);
+ if (machine)
+ machineResult(transaction_id, RESTORE_SPIFFS_CMD, "error", storageErrorCode(error, "RESTORE_FAILED"));
+ else
+ Serial.println("SPIFFS restore failed: " + error);
}
#else
- Serial.println(F("SD Card NOT Supported"));
+ if (machine)
+ machineResult(transaction_id, RESTORE_SPIFFS_CMD, "error", "SD_NOT_SUPPORTED");
+ else
+ Serial.println(F("SD Card NOT Supported"));
#endif
}
// GCOVR_EXCL_STOP
diff --git a/esp32_marauder/CommandLine.h b/esp32_marauder/CommandLine.h
index 1b2857073..b695a9f73 100644
--- a/esp32_marauder/CommandLine.h
+++ b/esp32_marauder/CommandLine.h
@@ -55,7 +55,9 @@ const char PROGMEM UPDATE_CMD[] = "update";
const char PROGMEM HELP_CMD[] = "help";
const char PROGMEM SETTINGS_CMD[] = "settings";
const char PROGMEM LS_CMD[] = "ls";
+const char PROGMEM PROTOCOL_INFO_CMD[] = "protocolinfo";
const char PROGMEM BACKUP_SPIFFS_CMD[] = "backupspiffs";
+const char PROGMEM BACKUP_STATUS_CMD[] = "backupstatus";
const char PROGMEM RESTORE_SPIFFS_CMD[] = "restorespiffs";
const char PROGMEM LED_CMD[] = "led";
const char PROGMEM GPS_DATA_CMD[] = "gpsdata";
@@ -135,8 +137,10 @@ const char PROGMEM HELP_REBOOT_CMD[] = "reboot";
const char PROGMEM HELP_UPDATE_CMD_A[] = "update -s/-w";
const char PROGMEM HELP_SETTINGS_CMD[] = "settings [-s enable/disable>]/[-r]";
const char PROGMEM HELP_LS_CMD[] = "ls ";
-const char PROGMEM HELP_BACKUP_SPIFFS_CMD[] = "backupspiffs - copy SPIFFS to /spiffs on SD";
-const char PROGMEM HELP_RESTORE_SPIFFS_CMD[] = "restorespiffs - restore SPIFFS from /spiffs on SD";
+const char PROGMEM HELP_PROTOCOL_INFO_CMD[] = "protocolinfo [--machine ]";
+const char PROGMEM HELP_BACKUP_SPIFFS_CMD[] = "backupspiffs [--machine ] - copy SPIFFS to /spiffs on SD";
+const char PROGMEM HELP_BACKUP_STATUS_CMD[] = "backupstatus [--machine ] - inspect /spiffs on SD";
+const char PROGMEM HELP_RESTORE_SPIFFS_CMD[] = "restorespiffs [--machine ] - restore SPIFFS from /spiffs on SD";
const char PROGMEM HELP_LED_CMD[] = "led -s /-p ";
const char PROGMEM HELP_GPS_DATA_CMD[] = "gpsdata";
const char PROGMEM HELP_GPS_CMD[] = "gps [-t] [-g] \r\n [-n] \r\n [-b = use BD vs GB for beidou]";
diff --git a/esp32_marauder/SDInterface.cpp b/esp32_marauder/SDInterface.cpp
index d35c94dff..caf8cad2a 100644
--- a/esp32_marauder/SDInterface.cpp
+++ b/esp32_marauder/SDInterface.cpp
@@ -150,6 +150,41 @@ namespace {
source_node.close();
return true;
}
+
+ bool measureTree(
+ fs::FS& fs,
+ const String& path,
+ size_t& files_found,
+ size_t& bytes_found,
+ String& error
+ ) {
+ File node = fs.open(path);
+ if (!node) {
+ error = "Could not open backup path " + path;
+ return false;
+ }
+
+ if (!node.isDirectory()) {
+ bytes_found += node.size();
+ files_found++;
+ node.close();
+ return true;
+ }
+
+ File child = node.openNextFile();
+ while (child) {
+ String child_path = child.path();
+ child.close();
+ if (!measureTree(fs, child_path, files_found, bytes_found, error)) {
+ node.close();
+ return false;
+ }
+ child = node.openNextFile();
+ }
+
+ node.close();
+ return true;
+ }
}
// GCOVR_EXCL_STOP
@@ -301,6 +336,27 @@ bool SDInterface::backupSPIFFS(size_t& files_copied, size_t& bytes_copied, Strin
return true;
}
+bool SDInterface::inspectSPIFFSBackup(size_t& files_found, size_t& bytes_found, String& error) {
+ files_found = 0;
+ bytes_found = 0;
+ error = "";
+
+ if (!this->supported) {
+ error = "SD card not detected";
+ return false;
+ }
+
+ File backup = SD.open("/spiffs");
+ bool valid_backup = backup && backup.isDirectory();
+ backup.close();
+ if (!valid_backup) {
+ error = "SD:/spiffs backup not found";
+ return false;
+ }
+
+ return measureTree(SD, "/spiffs", files_found, bytes_found, error);
+}
+
bool SDInterface::restoreSPIFFS(size_t& files_copied, size_t& bytes_copied, String& error) {
files_copied = 0;
bytes_copied = 0;
diff --git a/esp32_marauder/SDInterface.h b/esp32_marauder/SDInterface.h
index 1eafd62f5..07a93c314 100644
--- a/esp32_marauder/SDInterface.h
+++ b/esp32_marauder/SDInterface.h
@@ -70,6 +70,7 @@ class SDInterface {
void performUpdate(Stream &updateSource, size_t updateSize);
bool removeFile(String file_path);
bool backupSPIFFS(size_t& files_copied, size_t& bytes_copied, String& error);
+ bool inspectSPIFFSBackup(size_t& files_found, size_t& bytes_found, String& error);
bool restoreSPIFFS(size_t& files_copied, size_t& bytes_copied, String& error);
};
diff --git a/tools/test_spiffs_machine_protocol.py b/tools/test_spiffs_machine_protocol.py
new file mode 100644
index 000000000..ace9f3de4
--- /dev/null
+++ b/tools/test_spiffs_machine_protocol.py
@@ -0,0 +1,42 @@
+import re
+import unittest
+from pathlib import Path
+
+
+ROOT = Path(__file__).resolve().parents[1]
+
+
+class SpiffsMachineProtocolTests(unittest.TestCase):
+ def test_protocol_is_versioned_framed_and_transactional(self):
+ header = (ROOT / "esp32_marauder" / "CommandLine.h").read_text()
+ source = (ROOT / "esp32_marauder" / "CommandLine.cpp").read_text()
+
+ self.assertIn('PROTOCOL_INFO_CMD[] = "protocolinfo"', header)
+ self.assertIn('BACKUP_STATUS_CMD[] = "backupstatus"', header)
+ self.assertIn('MARAUDER_PROTOCOL_PREFIX = "@MARAUDER:"', source)
+ self.assertIn("MARAUDER_PROTOCOL_VERSION = 1", source)
+ self.assertIn('this->argSearch(&cmd_args, "--machine")', source)
+ self.assertIn('"INVALID_TRANSACTION"', source)
+ self.assertIn('"SD_NOT_SUPPORTED"', source)
+ self.assertRegex(source, r'machineResult\([^;]+"started"')
+ self.assertRegex(source, r'machineResult\([^;]+"success"')
+
+ def test_machine_restore_acknowledges_reboot(self):
+ source = (ROOT / "esp32_marauder" / "CommandLine.cpp").read_text()
+ restore = source[source.index("else if (cmd_args.get(0) == RESTORE_SPIFFS_CMD)") :]
+ success = restore.index('machineResult(transaction_id, RESTORE_SPIFFS_CMD, "success"')
+ restart = restore.index("ESP.restart();")
+ self.assertLess(success, restart)
+ self.assertIn("files_copied, bytes_copied, true", restore[success:restart])
+
+ def test_backup_status_measures_the_activated_backup(self):
+ source = (ROOT / "esp32_marauder" / "SDInterface.cpp").read_text()
+ method = re.search(
+ r"bool SDInterface::inspectSPIFFSBackup\(.*?\n\}", source, re.S
+ ).group(0)
+ self.assertIn('SD.open("/spiffs")', method)
+ self.assertIn('measureTree(SD, "/spiffs"', method)
+
+
+if __name__ == "__main__":
+ unittest.main()
From 33aeed36ae78cdd625adb57925bee88ecb328aef Mon Sep 17 00:00:00 2001
From: Just Call Me Koko <25190487+justcallmekoko@users.noreply.github.com>
Date: Sat, 22 Aug 2026 21:14:28 -0400
Subject: [PATCH 13/32] Avoid undefined board identity in protocol response
---
esp32_marauder/CommandLine.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/esp32_marauder/CommandLine.cpp b/esp32_marauder/CommandLine.cpp
index 8784d6f61..6c3bd5377 100644
--- a/esp32_marauder/CommandLine.cpp
+++ b/esp32_marauder/CommandLine.cpp
@@ -556,8 +556,6 @@ void CommandLine::runCommand(String input) {
Serial.print(jsonEscape(transaction_id));
Serial.print("\",\"command\":\"protocolinfo\",\"status\":\"success\",\"code\":\"OK\",\"firmware\":\"");
Serial.print(jsonEscape(version_number));
- Serial.print("\",\"board\":\"");
- Serial.print(jsonEscape(board_target));
#ifdef HAS_SD
Serial.println("\",\"capabilities\":[\"spiffs-backup\",\"spiffs-backup-status\",\"spiffs-restore\"],\"backupPath\":\"/spiffs\"}");
#else
From 3aa19a0d027e169502c6f33ea5ce6b84a816a94c Mon Sep 17 00:00:00 2001
From: Just Call Me Koko <25190487+justcallmekoko@users.noreply.github.com>
Date: Sat, 22 Aug 2026 21:23:14 -0400
Subject: [PATCH 14/32] Exclude serial help from native coverage
---
esp32_marauder/CommandLine.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/esp32_marauder/CommandLine.cpp b/esp32_marauder/CommandLine.cpp
index 6c3bd5377..bfac82612 100644
--- a/esp32_marauder/CommandLine.cpp
+++ b/esp32_marauder/CommandLine.cpp
@@ -305,8 +305,8 @@ void CommandLine::runCommand(String input) {
Serial.println(HELP_REBOOT_CMD);
Serial.println(HELP_UPDATE_CMD_A);
Serial.println(HELP_LS_CMD);
- Serial.println(HELP_PROTOCOL_INFO_CMD);
// GCOVR_EXCL_START -- hardware-only command help entry.
+ Serial.println(HELP_PROTOCOL_INFO_CMD);
#ifdef HAS_SD
Serial.println(HELP_BACKUP_SPIFFS_CMD);
Serial.println(HELP_BACKUP_STATUS_CMD);
From 34f9b679f452fd336ca22d4ccc24964b2db34582 Mon Sep 17 00:00:00 2001
From: Just Call Me Koko <25190487+justcallmekoko@users.noreply.github.com>
Date: Sun, 23 Aug 2026 17:15:34 -0400
Subject: [PATCH 15/32] Prepare v1.15.1 SPIFFS migration release
---
esp32_marauder/configs.h | 2 +-
tools/test_installer_manifest.py | 33 ++++++++++++++++++++++++++++++++
2 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/esp32_marauder/configs.h b/esp32_marauder/configs.h
index 72512aef6..41444ed34 100644
--- a/esp32_marauder/configs.h
+++ b/esp32_marauder/configs.h
@@ -42,7 +42,7 @@
#define JSON_SETTING_SIZE 2048
-#define MARAUDER_VERSION "v1.15.0"
+#define MARAUDER_VERSION "v1.15.1"
#define GRAPH_REFRESH 100
diff --git a/tools/test_installer_manifest.py b/tools/test_installer_manifest.py
index 531f7e955..e657213c9 100644
--- a/tools/test_installer_manifest.py
+++ b/tools/test_installer_manifest.py
@@ -81,6 +81,39 @@ def test_registry_contains_unique_complete_build_targets(self) -> None:
len(registry["targets"]),
)
+ def test_public_targets_keep_their_release_partition_layouts(self) -> None:
+ normal_boards = load_normal_build_matrix(NORMAL_WORKFLOW, REGISTRY)
+ normal_fqbns = {board["flag"]: board["fbqn"] for board in normal_boards}
+
+ self.assertFalse((REPOSITORY_ROOT / "esp32_marauder/partitions.csv").exists())
+
+ layout_exceptions = {
+ "MARAUDER_T_DONGLE_C5": (
+ "FlashSize=16M",
+ "PartitionScheme=custom",
+ ),
+ "MARAUDER_PANCAKE": (
+ "FlashSize=8M",
+ "PartitionScheme=default_8MB",
+ ),
+ }
+ for flag, fqbn in normal_fqbns.items():
+ if flag in layout_exceptions:
+ for setting in layout_exceptions[flag]:
+ self.assertIn(setting, fqbn)
+ else:
+ self.assertIn("PartitionScheme=min_spiffs", fqbn, flag)
+
+ workflow = NORMAL_WORKFLOW.read_text(encoding="utf-8")
+ self.assertIn(
+ "if: matrix.board.flag == 'MARAUDER_T_DONGLE_C5'",
+ workflow,
+ )
+ self.assertIn(
+ "cp installer/partitions/t_dongle_c5.csv esp32_marauder/partitions.csv",
+ workflow,
+ )
+
def test_build_matrix_parser_fails_closed_on_unsupported_syntax(self) -> None:
with tempfile.TemporaryDirectory() as temporary:
workflow = Path(temporary) / "build_parallel.yml"
From 207d67bc1d0a1e0f946498c2507393d4bb3a04d8 Mon Sep 17 00:00:00 2001
From: Just Call Me Koko <25190487+justcallmekoko@users.noreply.github.com>
Date: Sun, 23 Aug 2026 17:16:00 -0400
Subject: [PATCH 16/32] Normalize menu source line endings
---
esp32_marauder/MenuFunctions.cpp | 8906 +++++++++++++++---------------
1 file changed, 4453 insertions(+), 4453 deletions(-)
diff --git a/esp32_marauder/MenuFunctions.cpp b/esp32_marauder/MenuFunctions.cpp
index 06fc79ef8..e4c43f46b 100644
--- a/esp32_marauder/MenuFunctions.cpp
+++ b/esp32_marauder/MenuFunctions.cpp
@@ -1,1549 +1,1549 @@
-#include "MenuFunctions.h"
-#include "lang_var.h"
-
-#ifdef HAS_SCREEN
-
+#include "MenuFunctions.h"
+#include "lang_var.h"
+
+#ifdef HAS_SCREEN
+
extern const unsigned char menu_icons[][66];
extern LinkedList* access_points;
extern LinkedList* stations;
extern LinkedList* airtags;
extern LinkedList* flippers;
extern LinkedList* ble_devices;
-
-#ifdef HAS_MINI_SCREEN
-void MenuFunctions::drawMiniMenuButton(int b, int x, bool selected) {
- if (!current_menu || !current_menu->list || x < 0 || x >= current_menu->list->size())
- return;
-
- MenuNode mini_node = current_menu->list->get(x);
- bool is_setting_node = (mini_node.icon == SETTINGS && mini_node.color == TFTLIGHTGREY);
- uint16_t color = is_setting_node ? (mini_node.selected ? TFT_GREEN : TFT_RED) : this->getColor(mini_node.color);
- int16_t button_x = KEY_X - (KEY_W / 2);
- int16_t button_y = (KEY_Y + (b * (KEY_H + KEY_SPACING_Y))) - (KEY_H / 2);
-
- uint16_t background = selected ? (is_setting_node ? TFT_LIGHTGREY : color) : TFT_BLACK;
- uint16_t text_color = (selected && !is_setting_node) ? TFT_BLACK : color;
-
- display_obj.tft.setFreeFont(NULL);
- display_obj.tft.setTextSize(1);
- display_obj.tft.setTextWrap(false);
- display_obj.tft.fillRect(button_x, button_y - 4, KEY_W, KEY_H, background);
- display_obj.tft.setTextColor(text_color, background);
- display_obj.tft.setCursor(button_x + BUTTON_PADDING, button_y + (KEY_H / 2) - 8);
- display_obj.tft.print(current_menu->list->get(x).name);
-}
-#endif
-
-void MenuFunctions::buttonNotSelected(int b, int x) {
- if (x == -1)
- x = b;
-
- // Ensure b is within valid button index range
- b = (x - menu_start_index) % BUTTON_SCREEN_LIMIT;
-
- #ifdef HAS_MINI_SCREEN
- this->drawMiniMenuButton(b, x, false);
- #endif
-
- uint16_t color = (current_menu->list->get(x).icon == SETTINGS && current_menu->list->get(x).color == TFTLIGHTGREY) ? (current_menu->list->get(x).selected ? TFT_GREEN : TFT_RED) : this->getColor(current_menu->list->get(x).color);
- uint16_t icon_color = (current_menu->list->get(x).icon == SETTINGS && current_menu->list->get(x).color == TFTLIGHTGREY) ? TFT_LIGHTGREY : color;
-
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.setFreeFont(MENU_FONT);
- display_obj.key[b].initButton(&display_obj.tft, KEY_X, KEY_Y + b * (KEY_H + KEY_SPACING_Y), KEY_W, KEY_H, TFT_BLACK, TFT_BLACK, color, (char*)"", KEY_TEXTSIZE);
- display_obj.key[b].drawButton(false, current_menu->list->get(x).name);
- if ((current_menu->list->get(x).name != text09) && (current_menu->list->get(x).icon != 255))
- display_obj.tft.drawXBitmap(0,
- KEY_Y + (b * (KEY_H + KEY_SPACING_Y)) - (ICON_H / 2),
- menu_icons[current_menu->list->get(x).icon],
- ICON_W,
- ICON_H,
- TFT_BLACK,
- icon_color);
- display_obj.tft.setFreeFont(NULL);
- #endif
-}
-
-void MenuFunctions::buttonSelected(int b, int x) {
- if (x == -1)
- x = b;
-
- // Ensure b is within valid button index range
- b = (x - menu_start_index) % BUTTON_SCREEN_LIMIT;
-
- uint16_t color = this->getColor(current_menu->list->get(x).color);
-
- #ifdef HAS_MINI_SCREEN
- this->drawMiniMenuButton(b, x, true);
- #endif
-
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.setFreeFont(MENU_FONT);
- if (current_menu->list->get(x).icon == SETTINGS && current_menu->list->get(x).color == TFTLIGHTGREY) {
- uint16_t setting_color = current_menu->list->get(x).selected ? TFT_GREEN : TFT_RED;
- display_obj.key[b].initButton(&display_obj.tft, KEY_X, KEY_Y + b * (KEY_H + KEY_SPACING_Y), KEY_W, KEY_H, TFT_BLACK, TFT_LIGHTGREY, setting_color, (char*)"", KEY_TEXTSIZE);
- display_obj.key[b].drawButton(false, current_menu->list->get(x).name);
- display_obj.tft.drawXBitmap(0,
- KEY_Y + (b * (KEY_H + KEY_SPACING_Y)) - (ICON_H / 2),
- menu_icons[current_menu->list->get(x).icon],
- ICON_W,
- ICON_H,
- TFT_BLACK,
- TFT_LIGHTGREY);
- } else {
- display_obj.key[b].drawButton(true, current_menu->list->get(x).name);
- if ((current_menu->list->get(x).name != text09) && (current_menu->list->get(x).icon != 255))
- display_obj.tft.drawXBitmap(0,
- KEY_Y + (b * (KEY_H + KEY_SPACING_Y)) - (ICON_H / 2),
- menu_icons[current_menu->list->get(x).icon],
- ICON_W,
- ICON_H,
- TFT_BLACK,
- color);
- }
- display_obj.tft.setFreeFont(NULL);
- #endif
-}
-
-void MenuFunctions::displayMenuButtons() {
- #ifdef HAS_ILI9341
- // Draw lines to show each menu button
- for (int i = 0; i < 3; i++) {
-
- // Draw horizontal line on left
- display_obj.tft.drawLine(0,
- TFT_HEIGHT / 3 * (i),
- (TFT_WIDTH / 12) / 2,
- TFT_HEIGHT / 3 * (i),
- TFT_FARTGRAY);
-
- // Draw horizontal line on right
- display_obj.tft.drawLine(TFT_WIDTH - 1 - ((TFT_WIDTH / 12) / 2),
- TFT_HEIGHT / 3 * (i),
- TFT_WIDTH,
- TFT_HEIGHT / 3 * (i),
- TFT_FARTGRAY);
-
- // Draw vertical line on left
- display_obj.tft.drawLine(0,
- (TFT_HEIGHT / 3 * (i)) - ((TFT_WIDTH / 12) / 2),
- 0,
- (TFT_HEIGHT / 3 * (i)) + ((TFT_WIDTH / 12) / 2),
- TFT_FARTGRAY);
-
- // Draw vertical line on right
- display_obj.tft.drawLine(TFT_WIDTH - 1,
- (TFT_HEIGHT / 3 * (i)) - ((TFT_WIDTH / 12) / 2),
- TFT_WIDTH - 1,
- (TFT_HEIGHT / 3 * (i)) + ((TFT_WIDTH / 12) / 2),
- TFT_FARTGRAY);
- }
- #endif
-}
-
-// Function to check menu input
-void MenuFunctions::main(uint32_t currentTime)
-{
- #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
- this->updateKeyboard();
- #endif
-
- // Some function exited and we need to go back to normal
- if (display_obj.exit_draw) {
- if (wifi_scan_obj.currentScanMode != WIFI_CONNECTED)
- wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF;
- display_obj.exit_draw = false;
- this->orientDisplay();
- }
- if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
- (wifi_scan_obj.currentScanMode == WIFI_CONNECTED) ||
- (wifi_scan_obj.currentScanMode == OTA_UPDATE) ||
- (wifi_scan_obj.currentScanMode == ESP_UPDATE) ||
- (wifi_scan_obj.currentScanMode == SHOW_INFO) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_GPS_DATA) ||
- (wifi_scan_obj.currentScanMode == GPS_POI) ||
- (wifi_scan_obj.currentScanMode == GPS_TRACKER) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_GPS_NMEA)) {
- if (wifi_scan_obj.orient_display) {
- this->orientDisplay();
- wifi_scan_obj.orient_display = false;
- }
- }
-
- if (currentTime != 0) {
- if (currentTime - initTime >= BANNER_TIME) {
- this->initTime = millis();
- if ((wifi_scan_obj.currentScanMode != LV_JOIN_WIFI) &&
- (wifi_scan_obj.currentScanMode != LV_ADD_SSID))
- this->updateStatusBar();
-
- // Do channel analyzer stuff
- if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_ANALYZER)){
- #ifdef HAS_SCREEN
- this->setGraphScale(this->graphScaleCheck(wifi_scan_obj._analyzer_values));
-
- this->drawGraph(wifi_scan_obj._analyzer_values);
- #endif
- }
-
- if (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) {
- #ifdef HAS_SCREEN
- this->setGraphScale(this->graphScaleCheckSmall(wifi_scan_obj.channel_activity));
-
- this->drawGraphSmall(wifi_scan_obj.channel_activity);
-
- #endif
- }
- }
- }
-
-
- boolean pressed = false;
- // This is code from bodmer's keypad example
- uint16_t t_x = 0, t_y = 0; // To store the touch coordinates
-
- // Get the display buffer out of the way
- if ((wifi_scan_obj.currentScanMode != WIFI_SCAN_OFF ) &&
- (wifi_scan_obj.currentScanMode != WIFI_CONNECTED) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_BEACON_SPAM) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_AP_SPAM) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_CSA) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_QUIET) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_AUTH) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH_MANUAL) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH_TARGETED) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_BAD_MSG_TARGETED) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_BAD_MSG) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_SLEEP) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_SLEEP_TARGETED) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_MIMIC) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_FUNNY_BEACON) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_RICK_ROLL))
- display_obj.displayBuffer();
-
-
- int pre_getTouch = millis();
-
- #ifdef HAS_ILI9341
- if (!this->disable_touch)
- pressed = display_obj.updateTouch(&t_x, &t_y);
- #endif
-
-
- // Brightness gesture: hold top or bottom zone 1.5s to enter brightness mode
- #ifdef HAS_ILI9341
- if (pressed && (wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF ||
- wifi_scan_obj.currentScanMode == WIFI_CONNECTED)) {
- uint16_t zoneUp = TFT_HEIGHT * 25 / 100;
- uint16_t zoneDown = TFT_HEIGHT * 75 / 100;
- if (t_y < zoneUp || t_y >= zoneDown) {
- uint32_t hold_start = millis();
- uint16_t hx, hy;
- bool held = false;
- while (display_obj.updateTouch(&hx, &hy)) {
- if (millis() - hold_start >= 1500) {
- held = true;
- break;
- }
- delay(10);
- }
- if (held) {
- // Wait for release before entering brightness mode
- while (display_obj.updateTouch(&hx, &hy)) delay(10);
- this->brightnessMode();
- return;
- }
- }
- }
- #endif
-
- // POI button interception during wardrive — full width bottom bar
- #ifdef HAS_ILI9341
- if (pressed &&
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_WAR_DRIVE ||
- wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION_WAR_DRIVE)) {
- if (t_y >= (SCREEN_HEIGHT - 50)) {
- wifi_scan_obj.tagPOI(nullptr);
- // Brief green flash
- display_obj.tft.fillRect(0, SCREEN_HEIGHT - 50, SCREEN_WIDTH, 50, TFT_GREEN);
- display_obj.tft.setTextSize(2);
- #ifdef HAS_GPS
- if (gps_obj.getFixStatus())
- display_obj.tft.setTextColor(TFT_BLACK, TFT_GREEN);
- else
- #endif
- display_obj.tft.setTextColor(TFT_BLACK, TFT_RED);
- String poiFlash = "POI (" + String(wifi_scan_obj.poiCount) + ")";
- int16_t flashWidth = poiFlash.length() * 12;
- display_obj.tft.setCursor((SCREEN_WIDTH - flashWidth) / 2, SCREEN_HEIGHT - 33);
- display_obj.tft.print(poiFlash);
- delay(200);
- x = -1;
- y = -1;
- return;
- }
- }
- #endif
-
- // This is if there are scans/attacks going on
- #ifdef HAS_ILI9341
- if ((wifi_scan_obj.currentScanMode != WIFI_SCAN_OFF) &&
- (pressed) &&
- (wifi_scan_obj.currentScanMode != WIFI_CONNECTED) &&
- (wifi_scan_obj.currentScanMode != OTA_UPDATE) &&
- (wifi_scan_obj.currentScanMode != ESP_UPDATE) &&
- (wifi_scan_obj.currentScanMode != SHOW_INFO) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_GPS_DATA) &&
- (wifi_scan_obj.currentScanMode != GPS_POI) &&
- (wifi_scan_obj.currentScanMode != GPS_TRACKER) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_GPS_NMEA))
- {
- // Stop the current scan
- if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_SAE_COMMIT) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_DETECT_FOLLOW) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION_WAR_DRIVE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_WAR_DRIVE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_DISPLAY_AP_INFO) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_EVIL_PORTAL) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP_STA) ||
- (wifi_scan_obj.currentScanMode == WIFI_PING_SCAN) ||
- (wifi_scan_obj.currentScanMode == WIFI_ARP_SCAN) ||
- (wifi_scan_obj.currentScanMode == WIFI_PORT_SCAN_ALL) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_SSH) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_TELNET) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_DNS) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_SMTP) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_HTTP) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_HTTPS) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_RDP) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PWN) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PINESCAN) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_MULTISSID) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_ESPRESSIF) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_ALL) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BEACON_SPAM) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_AP_SPAM) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_CSA) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_QUIET) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_AUTH) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH_MANUAL) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH_TARGETED) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BAD_MSG_TARGETED) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BAD_MSG) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SLEEP) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SLEEP_TARGETED) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SAE_COMMIT) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_MIMIC) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_FUNNY_BEACON) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_RICK_ROLL) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BEACON_LIST) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_ALL) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_FOX_HUNT) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_FINDMY_LIVE) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_RAYBAN) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG_MON) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_FLIPPER) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_SIMPLE) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_SIMPLE_TWO) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_SOUR_APPLE) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_APPLE_JUICE) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_SWIFTPAIR_SPAM) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_SPAM_ALL) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_SAMSUNG_SPAM) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_GOOGLE_SPAM) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_FLIPPER_SPAM) ||
- (wifi_scan_obj.currentScanMode == BT_SPOOF_AIRTAG) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_WAR_DRIVE) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_WAR_DRIVE_CONT) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_SKIMMERS) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_ANALYZER))
- {
- wifi_scan_obj.StartScan(WIFI_SCAN_OFF);
-
- // If we don't do this, the text and button coordinates will be off
- display_obj.init();
-
- // Take us back to the menu
- changeMenu(current_menu, true);
- }
-
- x = -1;
- y = -1;
-
- return;
- }
- #endif
-
- #ifdef HAS_BUTTONS
-
- #if (C_BTN >= 0) && !defined(MARAUDER_CARDPUTER) && !defined(MARAUDER_CARDPUTER_ADV)
- bool c_btn_press = c_btn.justPressed();
- #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
- bool c_btn_press = this->isKeyPressed('(');
- #endif
-
- #ifndef HAS_ILI9341
-
- if ((c_btn_press) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_OFF) &&
- (wifi_scan_obj.currentScanMode != WIFI_CONNECTED) &&
- (wifi_scan_obj.currentScanMode != OTA_UPDATE) &&
- (wifi_scan_obj.currentScanMode != ESP_UPDATE) &&
- (wifi_scan_obj.currentScanMode != SHOW_INFO) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_GPS_DATA) &&
- (wifi_scan_obj.currentScanMode != GPS_POI) &&
- (wifi_scan_obj.currentScanMode != GPS_TRACKER) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_GPS_NMEA))
- {
- // Stop the current scan
- if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_SAE_COMMIT) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_DETECT_FOLLOW) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION_WAR_DRIVE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_RAW_CAPTURE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_WAR_DRIVE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_DISPLAY_AP_INFO) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_EVIL_PORTAL) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_FINDMY_LIVE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP_STA) ||
- (wifi_scan_obj.currentScanMode == WIFI_PING_SCAN) ||
- (wifi_scan_obj.currentScanMode == WIFI_ARP_SCAN) ||
- (wifi_scan_obj.currentScanMode == WIFI_PORT_SCAN_ALL) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_SSH) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_TELNET) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_DNS) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_SMTP) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_HTTP) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_HTTPS) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_RDP) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PWN) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PINESCAN) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_MULTISSID) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_ESPRESSIF) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_ALL) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_DEAUTH) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BEACON_SPAM) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_AP_SPAM) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_CSA) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_QUIET) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_AUTH) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH_MANUAL) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH_TARGETED) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BAD_MSG_TARGETED) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BAD_MSG) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SLEEP) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SLEEP_TARGETED) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SAE_COMMIT) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_MIMIC) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_FUNNY_BEACON) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_RICK_ROLL) ||
- (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BEACON_LIST) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_ALL) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_FOX_HUNT) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_RAYBAN) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG_MON) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_FLIPPER) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_SIMPLE) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_SIMPLE_TWO) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_SOUR_APPLE) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_APPLE_JUICE) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_SWIFTPAIR_SPAM) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_SPAM_ALL) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_SAMSUNG_SPAM) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_GOOGLE_SPAM) ||
- (wifi_scan_obj.currentScanMode == BT_ATTACK_FLIPPER_SPAM) ||
- (wifi_scan_obj.currentScanMode == BT_SPOOF_AIRTAG) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_WAR_DRIVE) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_WAR_DRIVE_CONT) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_SKIMMERS) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_EAPOL) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_ACTIVE_EAPOL) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_ACTIVE_LIST_EAPOL) ||
- (wifi_scan_obj.currentScanMode == WIFI_PACKET_MONITOR) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PACKET_RATE) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_ANALYZER))
- {
- wifi_scan_obj.StartScan(WIFI_SCAN_OFF);
-
- // Restore display state without full reinit to avoid screen flash
- #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
- display_obj.tft.setRotation(SCREEN_ORIENTATION);
- display_obj.clearScreen();
- #else
- display_obj.init();
- #endif
-
- // Take us back to the menu
- changeMenu(current_menu, true);
- }
-
- x = -1;
- y = -1;
-
- return;
- }
- #endif
-
- #endif
-
-
- // Check if any key coordinate boxes contain the touch coordinates
- // This is for when on a menu
- // Make sure to add certain scanning functions here or else
- // menu items will be selected while scans and attacks are running
- #ifdef HAS_ILI9341
- if ((wifi_scan_obj.currentScanMode != WIFI_ATTACK_BEACON_SPAM) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_AP_SPAM) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_CSA) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_QUIET) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_AUTH) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH_MANUAL) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH_TARGETED) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_BAD_MSG_TARGETED) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_BAD_MSG) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_SLEEP) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_SLEEP_TARGETED) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_SAE_COMMIT) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_MIMIC) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_PACKET_RATE) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_RAW_CAPTURE) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_CHAN_ANALYZER) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_CHAN_ACT) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_SIG_STREN) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_AP) &&
- (wifi_scan_obj.currentScanMode != BT_SCAN_FLOCK) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_PROBE) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_DEAUTH) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_FUNNY_BEACON) &&
- (wifi_scan_obj.currentScanMode != WIFI_SCAN_EAPOL) &&
- (wifi_scan_obj.currentScanMode != WIFI_ATTACK_RICK_ROLL))
- {
- // Need this to set all keys to false
- /*for (uint8_t b = 0; b < BUTTON_ARRAY_LEN; b++) {
- if (pressed && display_obj.key[b].contains(t_x, t_y)) {
- display_obj.key[b].press(true); // tell the button it is pressed
- } else {
- display_obj.key[b].press(false); // tell the button it is NOT pressed
- }
- }*/
-
- // Detect up, down, select
- uint8_t menu_button = display_obj.menuButton(&t_x, &t_y, pressed);
-
- if (menu_button > -1) {
- if (menu_button == UP_BUTTON) {
- if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
- (wifi_scan_obj.currentScanMode == WIFI_CONNECTED) ||
- (wifi_scan_obj.currentScanMode == OTA_UPDATE)) {
- if (current_menu->selected > 0) {
- current_menu->selected--;
- // Page up
- if (current_menu->selected < this->menu_start_index) {
- this->buildButtons(current_menu, current_menu->selected);
- this->displayCurrentMenu(current_menu->selected);
- }
- this->buttonSelected(current_menu->selected - this->menu_start_index, current_menu->selected);
- if (!current_menu->list->get(current_menu->selected + 1).selected || (current_menu->list->get(current_menu->selected + 1).icon == SETTINGS && current_menu->list->get(current_menu->selected + 1).color == TFTLIGHTGREY))
- this->buttonNotSelected(current_menu->selected + 1 - this->menu_start_index, current_menu->selected + 1);
- }
- // Loop to end
- else {
- current_menu->selected = current_menu->list->size() - 1;
- if (current_menu->selected >= BUTTON_SCREEN_LIMIT) {
- this->buildButtons(current_menu, current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
- this->displayCurrentMenu(current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
- }
- this->buttonSelected(current_menu->selected, current_menu->selected);
- if (!current_menu->list->get(0).selected || (current_menu->list->get(0).icon == SETTINGS && current_menu->list->get(0).color == TFTLIGHTGREY))
- this->buttonNotSelected(0, this->menu_start_index);
- }
- }
- else if ((wifi_scan_obj.currentScanMode == WIFI_PACKET_MONITOR) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_EAPOL) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PACKET_RATE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_RAW_CAPTURE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_DEAUTH) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN)) {
- #ifndef HAS_DUAL_BAND
- if (wifi_scan_obj.set_channel < 14)
- wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel + 1);
- else
- wifi_scan_obj.changeChannel(1);
- #else
- if (wifi_scan_obj.dual_band_channel_index < DUAL_BAND_CHANNELS - 1)
- wifi_scan_obj.dual_band_channel_index++;
- else
- wifi_scan_obj.dual_band_channel_index = 0;
-
- wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
- #endif
- }
- else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) {
- #ifndef HAS_DUAL_BAND
- if (wifi_scan_obj.activity_page < MAX_CHANNEL / CHAN_PER_PAGE) {
- wifi_scan_obj.activity_page++;
- }
- #else
- if (wifi_scan_obj.activity_page < DUAL_BAND_CHANNELS / CHAN_PER_PAGE) {
- wifi_scan_obj.activity_page++;
- }
- #endif
- wifi_scan_obj.drawChannelLine();
- }
- }
- if (menu_button == DOWN_BUTTON) {
- if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
- (wifi_scan_obj.currentScanMode == WIFI_CONNECTED) ||
- (wifi_scan_obj.currentScanMode == OTA_UPDATE)) {
- if (current_menu->selected < current_menu->list->size() - 1) {
- current_menu->selected++;
- // Page down
- if (current_menu->selected - this->menu_start_index >= BUTTON_SCREEN_LIMIT) {
- this->buildButtons(current_menu, current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
- this->displayCurrentMenu(current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
- }
- else
- this->buttonSelected(current_menu->selected - this->menu_start_index, current_menu->selected);
- if (!current_menu->list->get(current_menu->selected - 1).selected || (current_menu->list->get(current_menu->selected - 1).icon == SETTINGS && current_menu->list->get(current_menu->selected - 1).color == TFTLIGHTGREY))
- this->buttonNotSelected(current_menu->selected - 1 - this->menu_start_index, current_menu->selected - 1);
- }
- // Loop to beginning
- else {
- if (current_menu->selected >= BUTTON_SCREEN_LIMIT) {
- current_menu->selected = 0;
- this->buildButtons(current_menu);
- this->displayCurrentMenu();
- this->buttonSelected(current_menu->selected);
- }
- else {
- current_menu->selected = 0;
- this->buttonSelected(current_menu->selected);
- if (!current_menu->list->get(current_menu->list->size() - 1).selected || (current_menu->list->get(current_menu->list->size() - 1).icon == SETTINGS && current_menu->list->get(current_menu->list->size() - 1).color == TFTLIGHTGREY))
- this->buttonNotSelected(current_menu->list->size() - 1);
- }
- }
- }
- else if ((wifi_scan_obj.currentScanMode == WIFI_PACKET_MONITOR) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_EAPOL) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PACKET_RATE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_RAW_CAPTURE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_DEAUTH) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN)) {
- #ifndef HAS_DUAL_BAND
- if (wifi_scan_obj.set_channel > 1)
- wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel - 1);
- else
- wifi_scan_obj.changeChannel(14);
- #else
- if (wifi_scan_obj.dual_band_channel_index > 0)
- wifi_scan_obj.dual_band_channel_index--;
- else
- wifi_scan_obj.dual_band_channel_index = DUAL_BAND_CHANNELS - 1;
-
- wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
- #endif
- }
- else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) {
- #ifndef HAS_DUAL_BAND
- if (wifi_scan_obj.activity_page > 1) {
- wifi_scan_obj.activity_page--;
- }
- #else
- if (wifi_scan_obj.activity_page > 0) {
- wifi_scan_obj.activity_page--;
- }
- #endif
- wifi_scan_obj.drawChannelLine();
- }
- }
- if(menu_button == SELECT_BUTTON) {
- current_menu->list->get(current_menu->selected).callable();
- }
- else {
- if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
- (wifi_scan_obj.currentScanMode == WIFI_CONNECTED))
- this->displayMenuButtons();
- }
- }
- }
- x = -1;
- y = -1;
- #endif
-
- // Menu navigation and paging
- #ifdef HAS_BUTTONS
- // Don't do this for touch screens
- #if !(defined(MARAUDER_V6) || defined(MARAUDER_V6_1) || defined(MARAUDER_CYD_MICRO) || defined(MARAUDER_CYD_GUITION) || defined(MARAUDER_CYD_2USB) || defined(MARAUDER_CYD_3_5_INCH))
- #if !defined(MARAUDER_M5STICKC) || defined(MARAUDER_M5STICKCP2)
- #if (U_BTN >= 0 || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV))
- #if (U_BTN >= 0)
- if (u_btn.justPressed()) {
- #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
- if (this->isKeyPressed(';')) {
- #endif
- if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
- (wifi_scan_obj.currentScanMode == WIFI_CONNECTED) ||
- (wifi_scan_obj.currentScanMode == OTA_UPDATE)) {
- if (current_menu->selected > 0) {
- current_menu->selected--;
- // Page up
- if (current_menu->selected < this->menu_start_index) {
- this->buildButtons(current_menu, current_menu->selected);
- this->displayCurrentMenu(current_menu->selected);
- }
- this->buttonSelected(current_menu->selected - this->menu_start_index, current_menu->selected);
- if (!current_menu->list->get(current_menu->selected + 1).selected || (current_menu->list->get(current_menu->selected + 1).icon == SETTINGS && current_menu->list->get(current_menu->selected + 1).color == TFTLIGHTGREY))
- this->buttonNotSelected(current_menu->selected + 1 - this->menu_start_index, current_menu->selected + 1);
- }
- // Loop to end
- else {
- current_menu->selected = current_menu->list->size() - 1;
- if (current_menu->selected >= BUTTON_SCREEN_LIMIT) {
- this->buildButtons(current_menu, current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
- this->displayCurrentMenu(current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
- }
- this->buttonSelected(current_menu->selected, current_menu->selected);
- if (!current_menu->list->get(0).selected || (current_menu->list->get(0).icon == SETTINGS && current_menu->list->get(0).color == TFTLIGHTGREY))
- this->buttonNotSelected(0, this->menu_start_index);
- }
- }
- else if ((wifi_scan_obj.currentScanMode == WIFI_PACKET_MONITOR) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_EAPOL) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PACKET_RATE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_RAW_CAPTURE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_DEAUTH) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN)) {
- #ifndef HAS_DUAL_BAND
- if (wifi_scan_obj.set_channel < 14)
- wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel + 1);
- else
- wifi_scan_obj.changeChannel(1);
- #else
- if (wifi_scan_obj.dual_band_channel_index < DUAL_BAND_CHANNELS - 1)
- wifi_scan_obj.dual_band_channel_index++;
- else
- wifi_scan_obj.dual_band_channel_index = 0;
-
- wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
- #endif
- }
- else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) {
- #ifndef HAS_DUAL_BAND
- if (wifi_scan_obj.activity_page < MAX_CHANNEL / CHAN_PER_PAGE) {
- wifi_scan_obj.activity_page++;
- }
- #else
- if (wifi_scan_obj.activity_page < DUAL_BAND_CHANNELS / CHAN_PER_PAGE) {
- wifi_scan_obj.activity_page++;
- }
- #endif
- wifi_scan_obj.drawChannelLine();
- }
- }
- #endif
- #endif
-
- #if (D_BTN >= 0 || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV))
- #if (D_BTN >= 0)
- if (d_btn.justPressed()){
- #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
- if (this->isKeyPressed('.')){
- #endif
- if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
- (wifi_scan_obj.currentScanMode == WIFI_CONNECTED) ||
- (wifi_scan_obj.currentScanMode == OTA_UPDATE)) {
- if (current_menu->selected < current_menu->list->size() - 1) {
- current_menu->selected++;
- // Page down
- if (current_menu->selected - this->menu_start_index >= BUTTON_SCREEN_LIMIT) {
- this->buildButtons(current_menu, current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
- this->displayCurrentMenu(current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
- }
- else
- this->buttonSelected(current_menu->selected - this->menu_start_index, current_menu->selected);
- if (!current_menu->list->get(current_menu->selected - 1).selected || (current_menu->list->get(current_menu->selected - 1).icon == SETTINGS && current_menu->list->get(current_menu->selected - 1).color == TFTLIGHTGREY))
- this->buttonNotSelected(current_menu->selected - 1 - this->menu_start_index, current_menu->selected - 1);
- }
- // Loop to beginning
- else {
- if (current_menu->selected >= BUTTON_SCREEN_LIMIT) {
- current_menu->selected = 0;
- this->buildButtons(current_menu);
- this->displayCurrentMenu();
- this->buttonSelected(current_menu->selected);
- }
- else {
- current_menu->selected = 0;
- this->buttonSelected(current_menu->selected);
- if (!current_menu->list->get(current_menu->list->size() - 1).selected || (current_menu->list->get(current_menu->list->size() - 1).icon == SETTINGS && current_menu->list->get(current_menu->list->size() - 1).color == TFTLIGHTGREY))
- this->buttonNotSelected(current_menu->list->size() - 1);
- }
- }
- }
- else if ((wifi_scan_obj.currentScanMode == WIFI_PACKET_MONITOR) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_EAPOL) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PACKET_RATE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_RAW_CAPTURE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
- (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_DEAUTH) ||
- (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN)) {
- #ifndef HAS_DUAL_BAND
- if (wifi_scan_obj.set_channel > 1)
- wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel - 1);
- else
- wifi_scan_obj.changeChannel(14);
- #else
- if (wifi_scan_obj.dual_band_channel_index > 0)
- wifi_scan_obj.dual_band_channel_index--;
- else
- wifi_scan_obj.dual_band_channel_index = DUAL_BAND_CHANNELS - 1;
-
- wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
- #endif
- }
- else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) {
- #ifndef HAS_DUAL_BAND
- if (wifi_scan_obj.activity_page > 1) {
- wifi_scan_obj.activity_page--;
- }
- #else
- if (wifi_scan_obj.activity_page > 0) {
- wifi_scan_obj.activity_page--;
- }
- #endif
- wifi_scan_obj.drawChannelLine();
- }
- }
- #endif
-
- #if (R_BTN >= 0 || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV))
- #if (R_BTN >= 0)
- if (r_btn.justPressed()) {
- #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
- if (this->isKeyPressed('/')) {
- #endif
- if (wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) {
- #ifndef HAS_DUAL_BAND
- if (wifi_scan_obj.set_channel < 14)
- wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel + 1);
- else
- wifi_scan_obj.changeChannel(1);
- #else
- if (wifi_scan_obj.dual_band_channel_index < DUAL_BAND_CHANNELS - 1)
- wifi_scan_obj.dual_band_channel_index++;
- else
- wifi_scan_obj.dual_band_channel_index = 0;
-
- wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
- #endif
- }
- }
- #endif
-
- #if (L_BTN >= 0 || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV))
- #if (L_BTN >= 0)
- if (l_btn.justPressed()) {
- #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
- if (this->isKeyPressed(',')) {
- #endif
- if (wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) {
- #ifndef HAS_DUAL_BAND
- if (wifi_scan_obj.set_channel > 1)
- wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel - 1);
- else
- wifi_scan_obj.changeChannel(14);
- #else
- if (wifi_scan_obj.dual_band_channel_index > 0)
- wifi_scan_obj.dual_band_channel_index--;
- else
- wifi_scan_obj.dual_band_channel_index = DUAL_BAND_CHANNELS - 1;
-
- wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
- #endif
- }
- }
- #endif
-
- #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
- if (this->isKeyPressed('`') || this->isKeyPressed(KEY_BACKSPACE)) {
- if (wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) {
- if (current_menu->parentMenu != NULL) {
- this->changeMenu(current_menu->parentMenu, true);
- }
- }
- }
- #endif
-
- if(c_btn_press){
- current_menu->list->get(current_menu->selected).callable();
- }
-
- #endif
- #endif
-}
-
-#if BATTERY_ANALOG_ON == 1
-byte battery_analog_array[10];
-byte battery_count = 0;
-byte battery_analog_last = 101;
-#define BATTERY_CHECK 50
-uint16_t battery_analog = 0;
-void MenuFunctions::battery(bool initial)
-{
- if (BATTERY_ANALOG_ON) {
- uint8_t n = 0;
- byte battery_analog_sample[10];
- byte deviation;
- if (battery_count == BATTERY_CHECK - 5) digitalWrite(BATTERY_PIN, HIGH);
- else if (battery_count == 5) digitalWrite(BATTERY_PIN, LOW);
- if (battery_count == 0) {
- battery_analog = 0;
- for (n = 9; n > 0; n--)battery_analog_array[n] = battery_analog_array[n - 1];
- for (n = 0; n < 10; n++) {
- battery_analog_sample[n] = map((analogRead(ANALOG_PIN) * 5), 2400, 4200, 0, 100);
- if (battery_analog_sample[n] > 100) battery_analog_sample[n] = 100;
- else if (battery_analog_sample[n] < 0) battery_analog_sample[n] = 0;
- battery_analog += battery_analog_sample[n];
- }
- battery_analog = battery_analog / 10;
- for (n = 0; n < 10; n++) {
- deviation = abs(battery_analog - battery_analog_sample[n]);
- if (deviation >= 10) battery_analog_sample[n] = battery_analog;
- }
- battery_analog = 0;
- for (n = 0; n < 10; n++) battery_analog += battery_analog_sample[n];
- battery_analog = battery_analog / 10;
- battery_analog_array[0] = battery_analog;
- if (battery_analog_array[9] > 0 ) {
- battery_analog = 0;
- for (n = 0; n < 10; n++) battery_analog += battery_analog_array[n];
- battery_analog = battery_analog / 10;
- }
- battery_count ++;
- }
- else if (battery_count < BATTERY_CHECK) battery_count++;
- else if (battery_count >= BATTERY_CHECK) battery_count = 0;
-
- if (battery_analog_last != battery_analog) {
- battery_analog_last = battery_analog;
- MenuFunctions::battery2();
- }
- }
-}
-void MenuFunctions::battery2(bool initial)
-{
- uint16_t the_color;
- if ( digitalRead(CHARGING_PIN) == 1) the_color = TFT_BLUE;
- else if (battery_analog < 20) the_color = TFT_RED;
- else if (battery_analog < 40) the_color = TFT_YELLOW;
- else the_color = TFT_GREEN;
-
- display_obj.tft.setTextColor(the_color, STATUSBAR_COLOR);
- display_obj.tft.fillRect(SB_TOUCH_X, 0, 50, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
- display_obj.tft.drawXBitmap(SB_TOUCH_X,
- 0,
- menu_icons[STATUS_BAT],
- 16,
- 16,
- STATUSBAR_COLOR,
- the_color);
- display_obj.tft.drawString((String) battery_analog + "%", SB_BAT_X, 0, 2);
-}
-#else
-void MenuFunctions::battery(bool initial)
-{
- #ifdef HAS_BATTERY
- uint16_t the_color;
- if (battery_obj.i2c_supported)
- {
- // Could use int compare maybe idk
- if (((String)battery_obj.battery_level != "25") && ((String)battery_obj.battery_level != "0"))
- the_color = TFT_GREEN;
- else
- the_color = TFT_RED;
-
- if ((battery_obj.battery_level != battery_obj.old_level) || (initial)) {
- battery_obj.old_level = battery_obj.battery_level;
- display_obj.tft.fillRect(204, 0, SCREEN_WIDTH, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
- }
-
- display_obj.tft.setCursor(0, 1);
- /*if (!this->disable_touch) {
- display_obj.tft.drawXBitmap(SB_TOUCH_X,
- 0,
- menu_icons[STATUS_BAT],
- 16,
- 16,
- STATUSBAR_COLOR,
- the_color);
- }*/
- #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
- display_obj.tft.drawString((String)battery_obj.battery_level + "%", SB_BAT_X, 0, 1);
- #else
- display_obj.tft.drawString((String)battery_obj.battery_level + "%", SB_BAT_X, 0, 2);
- #endif
- }
- #endif
-}
-void MenuFunctions::battery2(bool initial)
-{
- MenuFunctions::battery(initial);
-}
-#endif
-
-void MenuFunctions::updateStatusBar()
-{
- display_obj.tft.setTextSize(1);
-
- bool status_changed = false;
-
- #if defined(MARAUDER_MINI) || defined(MARAUDER_M5STICKC) || defined(MARAUDER_REV_FEATHER) || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) || defined(MARAUDER_MINI_V3)
- display_obj.tft.setFreeFont(NULL);
- #endif
-
- uint16_t the_color;
-
- #ifdef HAS_GPS
- if (this->old_gps_sat_count != gps_obj.getNumSats()) {
- this->old_gps_sat_count = gps_obj.getNumSats();
- display_obj.tft.fillRect(0, 0, SCREEN_WIDTH, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
- status_changed = true;
- }
- #endif
-
- // GPS Stuff
- #ifdef HAS_GPS
- if (gps_obj.getGpsModuleStatus()) {
- if (gps_obj.getFixStatus())
- the_color = TFT_GREEN;
- else
- the_color = TFT_RED;
-
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(4,
- 0,
- menu_icons[STATUS_GPS],
- 16,
- 16,
- STATUSBAR_COLOR,
- the_color);
- display_obj.tft.setTextColor(TFT_WHITE, STATUSBAR_COLOR, true);
-
- display_obj.tft.drawString(gps_obj.getNumSatsString(), 22, 0, 2);
- #elif defined(HAS_SCREEN)
- display_obj.tft.setTextColor(the_color, STATUSBAR_COLOR, true);
- display_obj.tft.drawString("GPS", 0, 0, 1);
- #endif
- }
- #endif
-
- display_obj.tft.setTextColor(TFT_WHITE, STATUSBAR_COLOR, true);
-
- // WiFi Channel Stuff
- uint8_t primaryChannel;
- wifi_second_chan_t secondChannel;
- esp_err_t err = esp_wifi_get_channel(&primaryChannel, &secondChannel);
-
- uint8_t current_channel = wifi_scan_obj.set_channel;
-
- if (err == ESP_OK)
- current_channel = primaryChannel;
-
- if ((current_channel != wifi_scan_obj.old_channel) || (status_changed)) {
- wifi_scan_obj.old_channel = current_channel;
- #if defined(MARAUDER_MINI) || defined(MARAUDER_M5STICKC) || defined(MARAUDER_REV_FEATHER) || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) || defined(MARAUDER_MINI_V3)
- display_obj.tft.fillRect(TFT_WIDTH/4, 0, CHAR_WIDTH * 6, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
- #elif defined(HAS_DUAL_BAND)
- display_obj.tft.fillRect(50, 0, (CHAR_WIDTH / 2) * 8, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
- #else
- display_obj.tft.fillRect(50, 0, (CHAR_WIDTH / 2) * 7, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
- #endif
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawString("CH: " + (String)wifi_scan_obj.old_channel, 50, 0, 2);
- #endif
-
- #ifdef HAS_MINI_SCREEN
- display_obj.tft.drawString("CH:" + (String)wifi_scan_obj.old_channel, TFT_WIDTH/4, 0, 1);
- #endif
- }
-
- // RAM Stuff
- wifi_scan_obj.free_ram = String(esp_get_free_heap_size());
- if ((wifi_scan_obj.free_ram != wifi_scan_obj.old_free_ram) || (status_changed)) {
- wifi_scan_obj.old_free_ram = wifi_scan_obj.free_ram;
- //display_obj.tft.fillRect(SB_MEM_X, 0, 60, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
- #ifdef HAS_FULL_SCREEN
- #ifndef HAS_PSRAM
- display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", SB_MEM_X, 0, 2);
- #else
- display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", SB_MEM_X, 0, 1);
- display_obj.tft.drawString("P:" + String(getPSRAMUsagePercent()) + "%", SB_MEM_X, 8, 1);
- #endif
- #endif
-
- #ifdef HAS_MINI_SCREEN
- display_obj.tft.drawString(String(getDRAMUsagePercent()) + "%", TFT_WIDTH/1.75, 0, 1);
- #endif
- }
-
- // Draw battery info
- MenuFunctions::battery(false);
- display_obj.tft.fillRect(186, 0, 16, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
-
- // Disable touch stuff
- #ifdef HAS_ILI9341
- #ifdef HAS_BUTTONS
- if (this->disable_touch) {
- display_obj.tft.setCursor(0, 1);
- display_obj.tft.drawXBitmap(SB_TOUCH_X,
- 0,
- menu_icons[DISABLE_TOUCH],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_RED);
- }
- else {
- display_obj.tft.setCursor(0, 1);
- display_obj.tft.drawXBitmap(SB_TOUCH_X,
- 0,
- menu_icons[DISABLE_TOUCH],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_DARKGREY);
- }
- #endif
- #endif
-
- // Draw SD info
- #ifdef HAS_SD
- if (sd_obj.supported)
- the_color = TFT_GREEN;
- else
- the_color = TFT_RED;
-
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(SB_SD_X,
- 0,
- menu_icons[STATUS_SD],
- 16,
- 16,
- STATUSBAR_COLOR,
- the_color);
- #endif
- #endif
-
- #ifdef HAS_MINI_SCREEN
- display_obj.tft.setTextColor(the_color, STATUSBAR_COLOR, true);
- display_obj.tft.drawString("SD", TFT_WIDTH - 12, 0, 1);
- #endif
-
- // WiFi connection status stuff
- if (wifi_scan_obj.wifi_connected) {
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(SB_WIFI_X,
- 0,
- menu_icons[JOINED],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_GREEN);
- #endif
- } else {
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(SB_WIFI_X,
- 0,
- menu_icons[JOINED],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_DARKGREY);
- #endif
- }
-
- // Force PMKID stuff
- if ((wifi_scan_obj.force_pmkid) || (wifi_scan_obj.ep_deauth)) {
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(SB_FORCE_X,
- 0,
- menu_icons[FORCE],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_GREEN);
- #endif
- } else {
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(SB_FORCE_X,
- 0,
- menu_icons[FORCE],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_DARKGREY);
- #endif
- }
-}
-
-void MenuFunctions::drawStatusBar()
-{
- display_obj.tft.setTextSize(1);
- #ifdef HAS_MINI_SCREEN
- display_obj.tft.setFreeFont(NULL);
- #endif
- display_obj.tft.fillRect(0, 0, SCREEN_WIDTH, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
- display_obj.tft.setTextColor(TFT_WHITE, STATUSBAR_COLOR);
-
- uint16_t the_color;
-
- // GPS Stuff
- #ifdef HAS_GPS
- if (gps_obj.getGpsModuleStatus()) {
- if (gps_obj.getFixStatus())
- the_color = TFT_GREEN;
- else
- the_color = TFT_RED;
-
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(4,
- 0,
- menu_icons[STATUS_GPS],
- 16,
- 16,
- STATUSBAR_COLOR,
- the_color);
- display_obj.tft.setTextColor(TFT_WHITE, STATUSBAR_COLOR);
-
- display_obj.tft.drawString(gps_obj.getNumSatsString(), 22, 0, 2);
- #endif
- }
- #endif
-
- display_obj.tft.setTextColor(TFT_WHITE, STATUSBAR_COLOR);
-
-
- // WiFi Channel Stuff
- uint8_t primaryChannel;
- wifi_second_chan_t secondChannel;
- esp_err_t err = esp_wifi_get_channel(&primaryChannel, &secondChannel);
-
- if (err == ESP_OK)
- wifi_scan_obj.old_channel = primaryChannel;
- else
- wifi_scan_obj.old_channel = wifi_scan_obj.set_channel;
-
- #ifdef HAS_MINI_SCREEN
- display_obj.tft.fillRect(43, 0, TFT_WIDTH * 0.21, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
- #else
- display_obj.tft.fillRect(50, 0, TFT_WIDTH * 0.21, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
- #endif
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawString("CH: " + (String)wifi_scan_obj.old_channel, 50, 0, 2);
- #endif
-
- #ifdef HAS_MINI_SCREEN
- display_obj.tft.drawString("CH:" + (String)wifi_scan_obj.old_channel, TFT_WIDTH/4, 0, 1);
- #endif
-
- // RAM Stuff
- wifi_scan_obj.free_ram = String(esp_get_free_heap_size());
- wifi_scan_obj.old_free_ram = wifi_scan_obj.free_ram;
- display_obj.tft.fillRect(100, 0, 60, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
- #ifdef HAS_FULL_SCREEN
- #ifndef HAS_PSRAM
- display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", SB_MEM_X, 0, 2);
- #else
- display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", SB_MEM_X, 0, 1);
- display_obj.tft.drawString("P:" + String(getPSRAMUsagePercent()) + "%", SB_MEM_X, 8, 1);
- #endif
- #endif
-
- #ifdef HAS_MINI_SCREEN
- display_obj.tft.drawString(String(getDRAMUsagePercent()) + "%", TFT_WIDTH/1.75, 0, 1);
- #endif
-
-
- MenuFunctions::battery(true);
- display_obj.tft.fillRect(186, 0, 16, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
-
-
- // Disable touch stuff
- #ifdef HAS_ILI9341
- #ifdef HAS_BUTTONS
- if (this->disable_touch) {
- display_obj.tft.setCursor(0, 1);
- display_obj.tft.drawXBitmap(SB_TOUCH_X,
- 0,
- menu_icons[DISABLE_TOUCH],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_RED);
- }
- else {
- display_obj.tft.setCursor(0, 1);
- display_obj.tft.drawXBitmap(SB_TOUCH_X,
- 0,
- menu_icons[DISABLE_TOUCH],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_DARKGREY);
- }
- #endif
- #endif
-
- // Draw SD info
- #ifdef HAS_SD
- if (sd_obj.supported)
- the_color = TFT_GREEN;
- else
- the_color = TFT_RED;
-
-
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(SB_SD_X,
- 0,
- menu_icons[STATUS_SD],
- 16,
- 16,
- STATUSBAR_COLOR,
- the_color);
- #endif
- #endif
-
- #ifdef HAS_MINI_SCREEN
- display_obj.tft.setTextColor(the_color, STATUSBAR_COLOR);
- display_obj.tft.drawString("SD", TFT_WIDTH - 12, 0, 1);
- #endif
-
- // WiFi connection status stuff
- if (wifi_scan_obj.wifi_connected) {
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(SB_WIFI_X,
- 0,
- menu_icons[JOINED],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_GREEN);
- #endif
- } else {
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(SB_WIFI_X,
- 0,
- menu_icons[JOINED],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_DARKGREY);
- #endif
- }
-
- // Force PMKID stuff
- if ((wifi_scan_obj.force_pmkid) || (wifi_scan_obj.ep_deauth)) {
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(SB_FORCE_X,
- 0,
- menu_icons[FORCE],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_GREEN);
- #endif
- } else {
- #ifdef HAS_FULL_SCREEN
- display_obj.tft.drawXBitmap(SB_FORCE_X,
- 0,
- menu_icons[FORCE],
- 16,
- 16,
- STATUSBAR_COLOR,
- TFT_DARKGREY);
- #endif
- }
-}
-
-void MenuFunctions::orientDisplay() {
- display_obj.init();
-
- display_obj.tft.setRotation(SCREEN_ORIENTATION); // Portrait
-
- display_obj.tft.setCursor(0, 0);
-
- #ifdef HAS_ILI9341
- #ifndef HAS_CYD_TOUCH
- display_obj.setCalData();
- #else
- display_obj.touchscreen.setRotation(0);
- #endif
- #endif
-
- changeMenu(current_menu, true);
-}
-
-const char* MenuFunctions::callSetting(const char* key) {
- specSettingMenu.name = key;
-
- const char* setting_type = settings_obj.getSettingType(key);
-
- if (setting_type && strcmp(setting_type, "bool") == 0) {
- return "bool";
- }
-
- return "";
-}
-
-/*void MenuFunctions::displaySetting(String key, Menu* menu, int index) {
- specSettingMenu.name = key;
-
- bool setting_value = settings_obj.loadSetting(key);
-
- // Make a local copy of menu node
- MenuNode node = menu->list->get(index);
-
- display_obj.tft.setTextWrap(false);
- display_obj.tft.setFreeFont(NULL);
- display_obj.tft.setCursor(0, 100);
- display_obj.tft.setTextSize(1);
-
- // Set local copy value
- if (!setting_value) {
- display_obj.tft.setTextColor(TFT_RED);
- display_obj.tft.println(F(text_table1[4]));
- node.selected = false;
- }
- else {
- display_obj.tft.setTextColor(TFT_GREEN);
- display_obj.tft.println(F(text_table1[5]));
- node.selected = true;
- }
-
- // Put local copy back into menu
- menu->list->set(index, node);
-
-}*/
-
-void MenuFunctions::displaySetting(const char* key, Menu* menu, int index) {
- specSettingMenu.name = String(key);
-
- bool setting_value = settings_obj.loadSetting(key);
-
- // Make a local copy of menu node
- MenuNode node = menu->list->get(index);
-
- display_obj.tft.setTextWrap(false);
- display_obj.tft.setFreeFont(NULL);
- display_obj.tft.setCursor(0, 100);
- display_obj.tft.setTextSize(1);
-
- // Set local copy value
- if (!setting_value) {
- display_obj.tft.setTextColor(TFT_RED);
- display_obj.tft.println(F(text_table1[4]));
- node.selected = false;
- } else {
- display_obj.tft.setTextColor(TFT_GREEN);
- display_obj.tft.println(F(text_table1[5]));
- node.selected = true;
- }
-
- // Put local copy back into menu
- menu->list->set(index, node);
-}
-
-#if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
-void MenuFunctions::updateKeyboard()
-{
- M5CardputerKeyboard.updateKeyList();
- M5CardputerKeyboard.updateKeysState();
-}
-
-bool MenuFunctions::isKeyPressed(char c)
-{
- bool pressed = M5CardputerKeyboard.isKeyPressed(c);
-
- if (pressed)
- delay(200);
-
- return pressed;
-}
-#endif
-
-#ifdef HAS_DIRECT_UPLOAD
- void MenuFunctions::buildUploadFileMenu() {
- if (sd_obj.supported) {
- this->setupSDFileList();
-
- uploadLogsMenu.list->clear();
- delete uploadLogsMenu.list;
- uploadLogsMenu.list = new LinkedList();
- uploadLogsMenu.name = "Logs";
-
- uploadLogsMenu.parentMenu = &wifiGeneralMenu;
-
- this->addNodes(&uploadLogsMenu, "Back", TFTLIGHTGREY, 0, [this]() {
- this->changeMenu(uploadLogsMenu.parentMenu, true);
- });
-
- this->addNodes(&uploadLogsMenu, "Delete Wardrive Logs", TFTORANGE, 0, [this]() {
- this->changeMenu(&deleteAllMenu, true);
- });
-
- this->addNodes(&uploadLogsMenu, "Upload All", TFTGREEN, 0, [this]() {
- this->changeMenu(&uploadAllMenu, true);
-
- });
-
- for (int i = 0; i < sd_obj.sd_files->size(); i++) {
- File current_file = sd_obj.getFile("/" + sd_obj.sd_files->get(i));
- if (sd_obj.sd_files->get(i).startsWith("wardrive_") || sd_obj.sd_files->get(i).startsWith("wigle-")) {
- if (!sd_obj.sd_files->get(i).endsWith(".wdg") && !sd_obj.sd_files->get(i).endsWith(".wigle") && !sd_obj.sd_files->get(i).endsWith(".gpx")) {
- this->addNodes(&uploadLogsMenu, sd_obj.sd_files->get(i).c_str(), TFTCYAN, 0, [this, i]() {
- sd_obj.selected_file_name = sd_obj.sd_files->get(i);
- Serial.println(sd_obj.sd_files->get(i) + " selected");
- this->changeMenu(&actionMenu, true);
- });
- }
- }
- }
-
- Serial.println("Built SD file menu with " + (String)sd_obj.sd_files->size() + " files");
- } else {
- Serial.println("SD Card not detected. Skipping menu creation...");
- }
- }
+
+#ifdef HAS_MINI_SCREEN
+void MenuFunctions::drawMiniMenuButton(int b, int x, bool selected) {
+ if (!current_menu || !current_menu->list || x < 0 || x >= current_menu->list->size())
+ return;
+
+ MenuNode mini_node = current_menu->list->get(x);
+ bool is_setting_node = (mini_node.icon == SETTINGS && mini_node.color == TFTLIGHTGREY);
+ uint16_t color = is_setting_node ? (mini_node.selected ? TFT_GREEN : TFT_RED) : this->getColor(mini_node.color);
+ int16_t button_x = KEY_X - (KEY_W / 2);
+ int16_t button_y = (KEY_Y + (b * (KEY_H + KEY_SPACING_Y))) - (KEY_H / 2);
+
+ uint16_t background = selected ? (is_setting_node ? TFT_LIGHTGREY : color) : TFT_BLACK;
+ uint16_t text_color = (selected && !is_setting_node) ? TFT_BLACK : color;
+
+ display_obj.tft.setFreeFont(NULL);
+ display_obj.tft.setTextSize(1);
+ display_obj.tft.setTextWrap(false);
+ display_obj.tft.fillRect(button_x, button_y - 4, KEY_W, KEY_H, background);
+ display_obj.tft.setTextColor(text_color, background);
+ display_obj.tft.setCursor(button_x + BUTTON_PADDING, button_y + (KEY_H / 2) - 8);
+ display_obj.tft.print(current_menu->list->get(x).name);
+}
+#endif
+
+void MenuFunctions::buttonNotSelected(int b, int x) {
+ if (x == -1)
+ x = b;
+
+ // Ensure b is within valid button index range
+ b = (x - menu_start_index) % BUTTON_SCREEN_LIMIT;
+
+ #ifdef HAS_MINI_SCREEN
+ this->drawMiniMenuButton(b, x, false);
+ #endif
+
+ uint16_t color = (current_menu->list->get(x).icon == SETTINGS && current_menu->list->get(x).color == TFTLIGHTGREY) ? (current_menu->list->get(x).selected ? TFT_GREEN : TFT_RED) : this->getColor(current_menu->list->get(x).color);
+ uint16_t icon_color = (current_menu->list->get(x).icon == SETTINGS && current_menu->list->get(x).color == TFTLIGHTGREY) ? TFT_LIGHTGREY : color;
+
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.setFreeFont(MENU_FONT);
+ display_obj.key[b].initButton(&display_obj.tft, KEY_X, KEY_Y + b * (KEY_H + KEY_SPACING_Y), KEY_W, KEY_H, TFT_BLACK, TFT_BLACK, color, (char*)"", KEY_TEXTSIZE);
+ display_obj.key[b].drawButton(false, current_menu->list->get(x).name);
+ if ((current_menu->list->get(x).name != text09) && (current_menu->list->get(x).icon != 255))
+ display_obj.tft.drawXBitmap(0,
+ KEY_Y + (b * (KEY_H + KEY_SPACING_Y)) - (ICON_H / 2),
+ menu_icons[current_menu->list->get(x).icon],
+ ICON_W,
+ ICON_H,
+ TFT_BLACK,
+ icon_color);
+ display_obj.tft.setFreeFont(NULL);
+ #endif
+}
+
+void MenuFunctions::buttonSelected(int b, int x) {
+ if (x == -1)
+ x = b;
+
+ // Ensure b is within valid button index range
+ b = (x - menu_start_index) % BUTTON_SCREEN_LIMIT;
+
+ uint16_t color = this->getColor(current_menu->list->get(x).color);
+
+ #ifdef HAS_MINI_SCREEN
+ this->drawMiniMenuButton(b, x, true);
+ #endif
+
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.setFreeFont(MENU_FONT);
+ if (current_menu->list->get(x).icon == SETTINGS && current_menu->list->get(x).color == TFTLIGHTGREY) {
+ uint16_t setting_color = current_menu->list->get(x).selected ? TFT_GREEN : TFT_RED;
+ display_obj.key[b].initButton(&display_obj.tft, KEY_X, KEY_Y + b * (KEY_H + KEY_SPACING_Y), KEY_W, KEY_H, TFT_BLACK, TFT_LIGHTGREY, setting_color, (char*)"", KEY_TEXTSIZE);
+ display_obj.key[b].drawButton(false, current_menu->list->get(x).name);
+ display_obj.tft.drawXBitmap(0,
+ KEY_Y + (b * (KEY_H + KEY_SPACING_Y)) - (ICON_H / 2),
+ menu_icons[current_menu->list->get(x).icon],
+ ICON_W,
+ ICON_H,
+ TFT_BLACK,
+ TFT_LIGHTGREY);
+ } else {
+ display_obj.key[b].drawButton(true, current_menu->list->get(x).name);
+ if ((current_menu->list->get(x).name != text09) && (current_menu->list->get(x).icon != 255))
+ display_obj.tft.drawXBitmap(0,
+ KEY_Y + (b * (KEY_H + KEY_SPACING_Y)) - (ICON_H / 2),
+ menu_icons[current_menu->list->get(x).icon],
+ ICON_W,
+ ICON_H,
+ TFT_BLACK,
+ color);
+ }
+ display_obj.tft.setFreeFont(NULL);
+ #endif
+}
+
+void MenuFunctions::displayMenuButtons() {
+ #ifdef HAS_ILI9341
+ // Draw lines to show each menu button
+ for (int i = 0; i < 3; i++) {
+
+ // Draw horizontal line on left
+ display_obj.tft.drawLine(0,
+ TFT_HEIGHT / 3 * (i),
+ (TFT_WIDTH / 12) / 2,
+ TFT_HEIGHT / 3 * (i),
+ TFT_FARTGRAY);
+
+ // Draw horizontal line on right
+ display_obj.tft.drawLine(TFT_WIDTH - 1 - ((TFT_WIDTH / 12) / 2),
+ TFT_HEIGHT / 3 * (i),
+ TFT_WIDTH,
+ TFT_HEIGHT / 3 * (i),
+ TFT_FARTGRAY);
+
+ // Draw vertical line on left
+ display_obj.tft.drawLine(0,
+ (TFT_HEIGHT / 3 * (i)) - ((TFT_WIDTH / 12) / 2),
+ 0,
+ (TFT_HEIGHT / 3 * (i)) + ((TFT_WIDTH / 12) / 2),
+ TFT_FARTGRAY);
+
+ // Draw vertical line on right
+ display_obj.tft.drawLine(TFT_WIDTH - 1,
+ (TFT_HEIGHT / 3 * (i)) - ((TFT_WIDTH / 12) / 2),
+ TFT_WIDTH - 1,
+ (TFT_HEIGHT / 3 * (i)) + ((TFT_WIDTH / 12) / 2),
+ TFT_FARTGRAY);
+ }
+ #endif
+}
+
+// Function to check menu input
+void MenuFunctions::main(uint32_t currentTime)
+{
+ #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+ this->updateKeyboard();
+ #endif
+
+ // Some function exited and we need to go back to normal
+ if (display_obj.exit_draw) {
+ if (wifi_scan_obj.currentScanMode != WIFI_CONNECTED)
+ wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF;
+ display_obj.exit_draw = false;
+ this->orientDisplay();
+ }
+ if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
+ (wifi_scan_obj.currentScanMode == WIFI_CONNECTED) ||
+ (wifi_scan_obj.currentScanMode == OTA_UPDATE) ||
+ (wifi_scan_obj.currentScanMode == ESP_UPDATE) ||
+ (wifi_scan_obj.currentScanMode == SHOW_INFO) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_GPS_DATA) ||
+ (wifi_scan_obj.currentScanMode == GPS_POI) ||
+ (wifi_scan_obj.currentScanMode == GPS_TRACKER) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_GPS_NMEA)) {
+ if (wifi_scan_obj.orient_display) {
+ this->orientDisplay();
+ wifi_scan_obj.orient_display = false;
+ }
+ }
+
+ if (currentTime != 0) {
+ if (currentTime - initTime >= BANNER_TIME) {
+ this->initTime = millis();
+ if ((wifi_scan_obj.currentScanMode != LV_JOIN_WIFI) &&
+ (wifi_scan_obj.currentScanMode != LV_ADD_SSID))
+ this->updateStatusBar();
+
+ // Do channel analyzer stuff
+ if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_ANALYZER)){
+ #ifdef HAS_SCREEN
+ this->setGraphScale(this->graphScaleCheck(wifi_scan_obj._analyzer_values));
+
+ this->drawGraph(wifi_scan_obj._analyzer_values);
+ #endif
+ }
+
+ if (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) {
+ #ifdef HAS_SCREEN
+ this->setGraphScale(this->graphScaleCheckSmall(wifi_scan_obj.channel_activity));
+
+ this->drawGraphSmall(wifi_scan_obj.channel_activity);
+
+ #endif
+ }
+ }
+ }
+
+
+ boolean pressed = false;
+ // This is code from bodmer's keypad example
+ uint16_t t_x = 0, t_y = 0; // To store the touch coordinates
+
+ // Get the display buffer out of the way
+ if ((wifi_scan_obj.currentScanMode != WIFI_SCAN_OFF ) &&
+ (wifi_scan_obj.currentScanMode != WIFI_CONNECTED) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_BEACON_SPAM) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_AP_SPAM) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_CSA) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_QUIET) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_AUTH) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH_MANUAL) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH_TARGETED) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_BAD_MSG_TARGETED) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_BAD_MSG) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_SLEEP) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_SLEEP_TARGETED) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_MIMIC) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_FUNNY_BEACON) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_RICK_ROLL))
+ display_obj.displayBuffer();
+
+
+ int pre_getTouch = millis();
+
+ #ifdef HAS_ILI9341
+ if (!this->disable_touch)
+ pressed = display_obj.updateTouch(&t_x, &t_y);
+ #endif
+
+
+ // Brightness gesture: hold top or bottom zone 1.5s to enter brightness mode
+ #ifdef HAS_ILI9341
+ if (pressed && (wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF ||
+ wifi_scan_obj.currentScanMode == WIFI_CONNECTED)) {
+ uint16_t zoneUp = TFT_HEIGHT * 25 / 100;
+ uint16_t zoneDown = TFT_HEIGHT * 75 / 100;
+ if (t_y < zoneUp || t_y >= zoneDown) {
+ uint32_t hold_start = millis();
+ uint16_t hx, hy;
+ bool held = false;
+ while (display_obj.updateTouch(&hx, &hy)) {
+ if (millis() - hold_start >= 1500) {
+ held = true;
+ break;
+ }
+ delay(10);
+ }
+ if (held) {
+ // Wait for release before entering brightness mode
+ while (display_obj.updateTouch(&hx, &hy)) delay(10);
+ this->brightnessMode();
+ return;
+ }
+ }
+ }
+ #endif
+
+ // POI button interception during wardrive — full width bottom bar
+ #ifdef HAS_ILI9341
+ if (pressed &&
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_WAR_DRIVE ||
+ wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION_WAR_DRIVE)) {
+ if (t_y >= (SCREEN_HEIGHT - 50)) {
+ wifi_scan_obj.tagPOI(nullptr);
+ // Brief green flash
+ display_obj.tft.fillRect(0, SCREEN_HEIGHT - 50, SCREEN_WIDTH, 50, TFT_GREEN);
+ display_obj.tft.setTextSize(2);
+ #ifdef HAS_GPS
+ if (gps_obj.getFixStatus())
+ display_obj.tft.setTextColor(TFT_BLACK, TFT_GREEN);
+ else
+ #endif
+ display_obj.tft.setTextColor(TFT_BLACK, TFT_RED);
+ String poiFlash = "POI (" + String(wifi_scan_obj.poiCount) + ")";
+ int16_t flashWidth = poiFlash.length() * 12;
+ display_obj.tft.setCursor((SCREEN_WIDTH - flashWidth) / 2, SCREEN_HEIGHT - 33);
+ display_obj.tft.print(poiFlash);
+ delay(200);
+ x = -1;
+ y = -1;
+ return;
+ }
+ }
+ #endif
+
+ // This is if there are scans/attacks going on
+ #ifdef HAS_ILI9341
+ if ((wifi_scan_obj.currentScanMode != WIFI_SCAN_OFF) &&
+ (pressed) &&
+ (wifi_scan_obj.currentScanMode != WIFI_CONNECTED) &&
+ (wifi_scan_obj.currentScanMode != OTA_UPDATE) &&
+ (wifi_scan_obj.currentScanMode != ESP_UPDATE) &&
+ (wifi_scan_obj.currentScanMode != SHOW_INFO) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_GPS_DATA) &&
+ (wifi_scan_obj.currentScanMode != GPS_POI) &&
+ (wifi_scan_obj.currentScanMode != GPS_TRACKER) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_GPS_NMEA))
+ {
+ // Stop the current scan
+ if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_SAE_COMMIT) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_DETECT_FOLLOW) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION_WAR_DRIVE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_WAR_DRIVE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_DISPLAY_AP_INFO) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_EVIL_PORTAL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP_STA) ||
+ (wifi_scan_obj.currentScanMode == WIFI_PING_SCAN) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ARP_SCAN) ||
+ (wifi_scan_obj.currentScanMode == WIFI_PORT_SCAN_ALL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_SSH) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_TELNET) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_DNS) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_SMTP) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_HTTP) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_HTTPS) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_RDP) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PWN) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PINESCAN) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_MULTISSID) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_ESPRESSIF) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_ALL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BEACON_SPAM) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_AP_SPAM) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_CSA) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_QUIET) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_AUTH) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH_MANUAL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH_TARGETED) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BAD_MSG_TARGETED) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BAD_MSG) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SLEEP) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SLEEP_TARGETED) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SAE_COMMIT) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_MIMIC) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_FUNNY_BEACON) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_RICK_ROLL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BEACON_LIST) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_ALL) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_FOX_HUNT) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_FINDMY_LIVE) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_RAYBAN) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG_MON) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_FLIPPER) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_SIMPLE) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_SIMPLE_TWO) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_SOUR_APPLE) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_APPLE_JUICE) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_SWIFTPAIR_SPAM) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_SPAM_ALL) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_SAMSUNG_SPAM) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_GOOGLE_SPAM) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_FLIPPER_SPAM) ||
+ (wifi_scan_obj.currentScanMode == BT_SPOOF_AIRTAG) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_WAR_DRIVE) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_WAR_DRIVE_CONT) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_SKIMMERS) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_ANALYZER))
+ {
+ wifi_scan_obj.StartScan(WIFI_SCAN_OFF);
+
+ // If we don't do this, the text and button coordinates will be off
+ display_obj.init();
+
+ // Take us back to the menu
+ changeMenu(current_menu, true);
+ }
+
+ x = -1;
+ y = -1;
+
+ return;
+ }
+ #endif
+
+ #ifdef HAS_BUTTONS
+
+ #if (C_BTN >= 0) && !defined(MARAUDER_CARDPUTER) && !defined(MARAUDER_CARDPUTER_ADV)
+ bool c_btn_press = c_btn.justPressed();
+ #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+ bool c_btn_press = this->isKeyPressed('(');
+ #endif
+
+ #ifndef HAS_ILI9341
+
+ if ((c_btn_press) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_OFF) &&
+ (wifi_scan_obj.currentScanMode != WIFI_CONNECTED) &&
+ (wifi_scan_obj.currentScanMode != OTA_UPDATE) &&
+ (wifi_scan_obj.currentScanMode != ESP_UPDATE) &&
+ (wifi_scan_obj.currentScanMode != SHOW_INFO) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_GPS_DATA) &&
+ (wifi_scan_obj.currentScanMode != GPS_POI) &&
+ (wifi_scan_obj.currentScanMode != GPS_TRACKER) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_GPS_NMEA))
+ {
+ // Stop the current scan
+ if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_SAE_COMMIT) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_DETECT_FOLLOW) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION_WAR_DRIVE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_RAW_CAPTURE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_WAR_DRIVE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_DISPLAY_AP_INFO) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_EVIL_PORTAL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_FINDMY_LIVE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP_STA) ||
+ (wifi_scan_obj.currentScanMode == WIFI_PING_SCAN) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ARP_SCAN) ||
+ (wifi_scan_obj.currentScanMode == WIFI_PORT_SCAN_ALL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_SSH) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_TELNET) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_DNS) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_SMTP) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_HTTP) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_HTTPS) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_RDP) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PWN) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PINESCAN) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_MULTISSID) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_ESPRESSIF) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_ALL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_DEAUTH) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BEACON_SPAM) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_AP_SPAM) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_CSA) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_QUIET) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_AUTH) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH_MANUAL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_DEAUTH_TARGETED) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BAD_MSG_TARGETED) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BAD_MSG) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SLEEP) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SLEEP_TARGETED) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_SAE_COMMIT) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_MIMIC) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_FUNNY_BEACON) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_RICK_ROLL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_ATTACK_BEACON_LIST) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_ALL) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_FOX_HUNT) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_RAYBAN) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG_MON) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_FLIPPER) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_SIMPLE) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_SIMPLE_TWO) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_SOUR_APPLE) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_APPLE_JUICE) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_SWIFTPAIR_SPAM) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_SPAM_ALL) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_SAMSUNG_SPAM) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_GOOGLE_SPAM) ||
+ (wifi_scan_obj.currentScanMode == BT_ATTACK_FLIPPER_SPAM) ||
+ (wifi_scan_obj.currentScanMode == BT_SPOOF_AIRTAG) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_WAR_DRIVE) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_WAR_DRIVE_CONT) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_SKIMMERS) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_EAPOL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_ACTIVE_EAPOL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_ACTIVE_LIST_EAPOL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_PACKET_MONITOR) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PACKET_RATE) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_ANALYZER))
+ {
+ wifi_scan_obj.StartScan(WIFI_SCAN_OFF);
+
+ // Restore display state without full reinit to avoid screen flash
+ #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+ display_obj.tft.setRotation(SCREEN_ORIENTATION);
+ display_obj.clearScreen();
+ #else
+ display_obj.init();
+ #endif
+
+ // Take us back to the menu
+ changeMenu(current_menu, true);
+ }
+
+ x = -1;
+ y = -1;
+
+ return;
+ }
+ #endif
+
+ #endif
+
+
+ // Check if any key coordinate boxes contain the touch coordinates
+ // This is for when on a menu
+ // Make sure to add certain scanning functions here or else
+ // menu items will be selected while scans and attacks are running
+ #ifdef HAS_ILI9341
+ if ((wifi_scan_obj.currentScanMode != WIFI_ATTACK_BEACON_SPAM) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_AP_SPAM) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_CSA) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_QUIET) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_AUTH) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH_MANUAL) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_DEAUTH_TARGETED) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_BAD_MSG_TARGETED) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_BAD_MSG) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_SLEEP) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_SLEEP_TARGETED) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_SAE_COMMIT) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_MIMIC) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_PACKET_RATE) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_RAW_CAPTURE) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_CHAN_ANALYZER) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_CHAN_ACT) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_SIG_STREN) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_AP) &&
+ (wifi_scan_obj.currentScanMode != BT_SCAN_FLOCK) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_PROBE) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_DEAUTH) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_FUNNY_BEACON) &&
+ (wifi_scan_obj.currentScanMode != WIFI_SCAN_EAPOL) &&
+ (wifi_scan_obj.currentScanMode != WIFI_ATTACK_RICK_ROLL))
+ {
+ // Need this to set all keys to false
+ /*for (uint8_t b = 0; b < BUTTON_ARRAY_LEN; b++) {
+ if (pressed && display_obj.key[b].contains(t_x, t_y)) {
+ display_obj.key[b].press(true); // tell the button it is pressed
+ } else {
+ display_obj.key[b].press(false); // tell the button it is NOT pressed
+ }
+ }*/
+
+ // Detect up, down, select
+ uint8_t menu_button = display_obj.menuButton(&t_x, &t_y, pressed);
+
+ if (menu_button > -1) {
+ if (menu_button == UP_BUTTON) {
+ if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
+ (wifi_scan_obj.currentScanMode == WIFI_CONNECTED) ||
+ (wifi_scan_obj.currentScanMode == OTA_UPDATE)) {
+ if (current_menu->selected > 0) {
+ current_menu->selected--;
+ // Page up
+ if (current_menu->selected < this->menu_start_index) {
+ this->buildButtons(current_menu, current_menu->selected);
+ this->displayCurrentMenu(current_menu->selected);
+ }
+ this->buttonSelected(current_menu->selected - this->menu_start_index, current_menu->selected);
+ if (!current_menu->list->get(current_menu->selected + 1).selected || (current_menu->list->get(current_menu->selected + 1).icon == SETTINGS && current_menu->list->get(current_menu->selected + 1).color == TFTLIGHTGREY))
+ this->buttonNotSelected(current_menu->selected + 1 - this->menu_start_index, current_menu->selected + 1);
+ }
+ // Loop to end
+ else {
+ current_menu->selected = current_menu->list->size() - 1;
+ if (current_menu->selected >= BUTTON_SCREEN_LIMIT) {
+ this->buildButtons(current_menu, current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
+ this->displayCurrentMenu(current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
+ }
+ this->buttonSelected(current_menu->selected, current_menu->selected);
+ if (!current_menu->list->get(0).selected || (current_menu->list->get(0).icon == SETTINGS && current_menu->list->get(0).color == TFTLIGHTGREY))
+ this->buttonNotSelected(0, this->menu_start_index);
+ }
+ }
+ else if ((wifi_scan_obj.currentScanMode == WIFI_PACKET_MONITOR) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_EAPOL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PACKET_RATE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_RAW_CAPTURE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_DEAUTH) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN)) {
+ #ifndef HAS_DUAL_BAND
+ if (wifi_scan_obj.set_channel < 14)
+ wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel + 1);
+ else
+ wifi_scan_obj.changeChannel(1);
+ #else
+ if (wifi_scan_obj.dual_band_channel_index < DUAL_BAND_CHANNELS - 1)
+ wifi_scan_obj.dual_band_channel_index++;
+ else
+ wifi_scan_obj.dual_band_channel_index = 0;
+
+ wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
+ #endif
+ }
+ else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) {
+ #ifndef HAS_DUAL_BAND
+ if (wifi_scan_obj.activity_page < MAX_CHANNEL / CHAN_PER_PAGE) {
+ wifi_scan_obj.activity_page++;
+ }
+ #else
+ if (wifi_scan_obj.activity_page < DUAL_BAND_CHANNELS / CHAN_PER_PAGE) {
+ wifi_scan_obj.activity_page++;
+ }
+ #endif
+ wifi_scan_obj.drawChannelLine();
+ }
+ }
+ if (menu_button == DOWN_BUTTON) {
+ if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
+ (wifi_scan_obj.currentScanMode == WIFI_CONNECTED) ||
+ (wifi_scan_obj.currentScanMode == OTA_UPDATE)) {
+ if (current_menu->selected < current_menu->list->size() - 1) {
+ current_menu->selected++;
+ // Page down
+ if (current_menu->selected - this->menu_start_index >= BUTTON_SCREEN_LIMIT) {
+ this->buildButtons(current_menu, current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
+ this->displayCurrentMenu(current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
+ }
+ else
+ this->buttonSelected(current_menu->selected - this->menu_start_index, current_menu->selected);
+ if (!current_menu->list->get(current_menu->selected - 1).selected || (current_menu->list->get(current_menu->selected - 1).icon == SETTINGS && current_menu->list->get(current_menu->selected - 1).color == TFTLIGHTGREY))
+ this->buttonNotSelected(current_menu->selected - 1 - this->menu_start_index, current_menu->selected - 1);
+ }
+ // Loop to beginning
+ else {
+ if (current_menu->selected >= BUTTON_SCREEN_LIMIT) {
+ current_menu->selected = 0;
+ this->buildButtons(current_menu);
+ this->displayCurrentMenu();
+ this->buttonSelected(current_menu->selected);
+ }
+ else {
+ current_menu->selected = 0;
+ this->buttonSelected(current_menu->selected);
+ if (!current_menu->list->get(current_menu->list->size() - 1).selected || (current_menu->list->get(current_menu->list->size() - 1).icon == SETTINGS && current_menu->list->get(current_menu->list->size() - 1).color == TFTLIGHTGREY))
+ this->buttonNotSelected(current_menu->list->size() - 1);
+ }
+ }
+ }
+ else if ((wifi_scan_obj.currentScanMode == WIFI_PACKET_MONITOR) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_EAPOL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PACKET_RATE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_RAW_CAPTURE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_DEAUTH) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN)) {
+ #ifndef HAS_DUAL_BAND
+ if (wifi_scan_obj.set_channel > 1)
+ wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel - 1);
+ else
+ wifi_scan_obj.changeChannel(14);
+ #else
+ if (wifi_scan_obj.dual_band_channel_index > 0)
+ wifi_scan_obj.dual_band_channel_index--;
+ else
+ wifi_scan_obj.dual_band_channel_index = DUAL_BAND_CHANNELS - 1;
+
+ wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
+ #endif
+ }
+ else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) {
+ #ifndef HAS_DUAL_BAND
+ if (wifi_scan_obj.activity_page > 1) {
+ wifi_scan_obj.activity_page--;
+ }
+ #else
+ if (wifi_scan_obj.activity_page > 0) {
+ wifi_scan_obj.activity_page--;
+ }
+ #endif
+ wifi_scan_obj.drawChannelLine();
+ }
+ }
+ if(menu_button == SELECT_BUTTON) {
+ current_menu->list->get(current_menu->selected).callable();
+ }
+ else {
+ if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
+ (wifi_scan_obj.currentScanMode == WIFI_CONNECTED))
+ this->displayMenuButtons();
+ }
+ }
+ }
+ x = -1;
+ y = -1;
+ #endif
+
+ // Menu navigation and paging
+ #ifdef HAS_BUTTONS
+ // Don't do this for touch screens
+ #if !(defined(MARAUDER_V6) || defined(MARAUDER_V6_1) || defined(MARAUDER_CYD_MICRO) || defined(MARAUDER_CYD_GUITION) || defined(MARAUDER_CYD_2USB) || defined(MARAUDER_CYD_3_5_INCH))
+ #if !defined(MARAUDER_M5STICKC) || defined(MARAUDER_M5STICKCP2)
+ #if (U_BTN >= 0 || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV))
+ #if (U_BTN >= 0)
+ if (u_btn.justPressed()) {
+ #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+ if (this->isKeyPressed(';')) {
+ #endif
+ if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
+ (wifi_scan_obj.currentScanMode == WIFI_CONNECTED) ||
+ (wifi_scan_obj.currentScanMode == OTA_UPDATE)) {
+ if (current_menu->selected > 0) {
+ current_menu->selected--;
+ // Page up
+ if (current_menu->selected < this->menu_start_index) {
+ this->buildButtons(current_menu, current_menu->selected);
+ this->displayCurrentMenu(current_menu->selected);
+ }
+ this->buttonSelected(current_menu->selected - this->menu_start_index, current_menu->selected);
+ if (!current_menu->list->get(current_menu->selected + 1).selected || (current_menu->list->get(current_menu->selected + 1).icon == SETTINGS && current_menu->list->get(current_menu->selected + 1).color == TFTLIGHTGREY))
+ this->buttonNotSelected(current_menu->selected + 1 - this->menu_start_index, current_menu->selected + 1);
+ }
+ // Loop to end
+ else {
+ current_menu->selected = current_menu->list->size() - 1;
+ if (current_menu->selected >= BUTTON_SCREEN_LIMIT) {
+ this->buildButtons(current_menu, current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
+ this->displayCurrentMenu(current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
+ }
+ this->buttonSelected(current_menu->selected, current_menu->selected);
+ if (!current_menu->list->get(0).selected || (current_menu->list->get(0).icon == SETTINGS && current_menu->list->get(0).color == TFTLIGHTGREY))
+ this->buttonNotSelected(0, this->menu_start_index);
+ }
+ }
+ else if ((wifi_scan_obj.currentScanMode == WIFI_PACKET_MONITOR) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_EAPOL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PACKET_RATE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_RAW_CAPTURE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_DEAUTH) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN)) {
+ #ifndef HAS_DUAL_BAND
+ if (wifi_scan_obj.set_channel < 14)
+ wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel + 1);
+ else
+ wifi_scan_obj.changeChannel(1);
+ #else
+ if (wifi_scan_obj.dual_band_channel_index < DUAL_BAND_CHANNELS - 1)
+ wifi_scan_obj.dual_band_channel_index++;
+ else
+ wifi_scan_obj.dual_band_channel_index = 0;
+
+ wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
+ #endif
+ }
+ else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) {
+ #ifndef HAS_DUAL_BAND
+ if (wifi_scan_obj.activity_page < MAX_CHANNEL / CHAN_PER_PAGE) {
+ wifi_scan_obj.activity_page++;
+ }
+ #else
+ if (wifi_scan_obj.activity_page < DUAL_BAND_CHANNELS / CHAN_PER_PAGE) {
+ wifi_scan_obj.activity_page++;
+ }
+ #endif
+ wifi_scan_obj.drawChannelLine();
+ }
+ }
+ #endif
+ #endif
+
+ #if (D_BTN >= 0 || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV))
+ #if (D_BTN >= 0)
+ if (d_btn.justPressed()){
+ #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+ if (this->isKeyPressed('.')){
+ #endif
+ if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
+ (wifi_scan_obj.currentScanMode == WIFI_CONNECTED) ||
+ (wifi_scan_obj.currentScanMode == OTA_UPDATE)) {
+ if (current_menu->selected < current_menu->list->size() - 1) {
+ current_menu->selected++;
+ // Page down
+ if (current_menu->selected - this->menu_start_index >= BUTTON_SCREEN_LIMIT) {
+ this->buildButtons(current_menu, current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
+ this->displayCurrentMenu(current_menu->selected + 1 - BUTTON_SCREEN_LIMIT);
+ }
+ else
+ this->buttonSelected(current_menu->selected - this->menu_start_index, current_menu->selected);
+ if (!current_menu->list->get(current_menu->selected - 1).selected || (current_menu->list->get(current_menu->selected - 1).icon == SETTINGS && current_menu->list->get(current_menu->selected - 1).color == TFTLIGHTGREY))
+ this->buttonNotSelected(current_menu->selected - 1 - this->menu_start_index, current_menu->selected - 1);
+ }
+ // Loop to beginning
+ else {
+ if (current_menu->selected >= BUTTON_SCREEN_LIMIT) {
+ current_menu->selected = 0;
+ this->buildButtons(current_menu);
+ this->displayCurrentMenu();
+ this->buttonSelected(current_menu->selected);
+ }
+ else {
+ current_menu->selected = 0;
+ this->buttonSelected(current_menu->selected);
+ if (!current_menu->list->get(current_menu->list->size() - 1).selected || (current_menu->list->get(current_menu->list->size() - 1).icon == SETTINGS && current_menu->list->get(current_menu->list->size() - 1).color == TFTLIGHTGREY))
+ this->buttonNotSelected(current_menu->list->size() - 1);
+ }
+ }
+ }
+ else if ((wifi_scan_obj.currentScanMode == WIFI_PACKET_MONITOR) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_EAPOL) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ANALYZER) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PACKET_RATE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_RAW_CAPTURE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
+ (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_DEAUTH) ||
+ (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN)) {
+ #ifndef HAS_DUAL_BAND
+ if (wifi_scan_obj.set_channel > 1)
+ wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel - 1);
+ else
+ wifi_scan_obj.changeChannel(14);
+ #else
+ if (wifi_scan_obj.dual_band_channel_index > 0)
+ wifi_scan_obj.dual_band_channel_index--;
+ else
+ wifi_scan_obj.dual_band_channel_index = DUAL_BAND_CHANNELS - 1;
+
+ wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
+ #endif
+ }
+ else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_CHAN_ACT) {
+ #ifndef HAS_DUAL_BAND
+ if (wifi_scan_obj.activity_page > 1) {
+ wifi_scan_obj.activity_page--;
+ }
+ #else
+ if (wifi_scan_obj.activity_page > 0) {
+ wifi_scan_obj.activity_page--;
+ }
+ #endif
+ wifi_scan_obj.drawChannelLine();
+ }
+ }
+ #endif
+
+ #if (R_BTN >= 0 || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV))
+ #if (R_BTN >= 0)
+ if (r_btn.justPressed()) {
+ #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+ if (this->isKeyPressed('/')) {
+ #endif
+ if (wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) {
+ #ifndef HAS_DUAL_BAND
+ if (wifi_scan_obj.set_channel < 14)
+ wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel + 1);
+ else
+ wifi_scan_obj.changeChannel(1);
+ #else
+ if (wifi_scan_obj.dual_band_channel_index < DUAL_BAND_CHANNELS - 1)
+ wifi_scan_obj.dual_band_channel_index++;
+ else
+ wifi_scan_obj.dual_band_channel_index = 0;
+
+ wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
+ #endif
+ }
+ }
+ #endif
+
+ #if (L_BTN >= 0 || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV))
+ #if (L_BTN >= 0)
+ if (l_btn.justPressed()) {
+ #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+ if (this->isKeyPressed(',')) {
+ #endif
+ if (wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) {
+ #ifndef HAS_DUAL_BAND
+ if (wifi_scan_obj.set_channel > 1)
+ wifi_scan_obj.changeChannel(wifi_scan_obj.set_channel - 1);
+ else
+ wifi_scan_obj.changeChannel(14);
+ #else
+ if (wifi_scan_obj.dual_band_channel_index > 0)
+ wifi_scan_obj.dual_band_channel_index--;
+ else
+ wifi_scan_obj.dual_band_channel_index = DUAL_BAND_CHANNELS - 1;
+
+ wifi_scan_obj.changeChannel(wifi_scan_obj.dual_band_channels[wifi_scan_obj.dual_band_channel_index]);
+ #endif
+ }
+ }
+ #endif
+
+ #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+ if (this->isKeyPressed('`') || this->isKeyPressed(KEY_BACKSPACE)) {
+ if (wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) {
+ if (current_menu->parentMenu != NULL) {
+ this->changeMenu(current_menu->parentMenu, true);
+ }
+ }
+ }
+ #endif
+
+ if(c_btn_press){
+ current_menu->list->get(current_menu->selected).callable();
+ }
+
+ #endif
+ #endif
+}
+
+#if BATTERY_ANALOG_ON == 1
+byte battery_analog_array[10];
+byte battery_count = 0;
+byte battery_analog_last = 101;
+#define BATTERY_CHECK 50
+uint16_t battery_analog = 0;
+void MenuFunctions::battery(bool initial)
+{
+ if (BATTERY_ANALOG_ON) {
+ uint8_t n = 0;
+ byte battery_analog_sample[10];
+ byte deviation;
+ if (battery_count == BATTERY_CHECK - 5) digitalWrite(BATTERY_PIN, HIGH);
+ else if (battery_count == 5) digitalWrite(BATTERY_PIN, LOW);
+ if (battery_count == 0) {
+ battery_analog = 0;
+ for (n = 9; n > 0; n--)battery_analog_array[n] = battery_analog_array[n - 1];
+ for (n = 0; n < 10; n++) {
+ battery_analog_sample[n] = map((analogRead(ANALOG_PIN) * 5), 2400, 4200, 0, 100);
+ if (battery_analog_sample[n] > 100) battery_analog_sample[n] = 100;
+ else if (battery_analog_sample[n] < 0) battery_analog_sample[n] = 0;
+ battery_analog += battery_analog_sample[n];
+ }
+ battery_analog = battery_analog / 10;
+ for (n = 0; n < 10; n++) {
+ deviation = abs(battery_analog - battery_analog_sample[n]);
+ if (deviation >= 10) battery_analog_sample[n] = battery_analog;
+ }
+ battery_analog = 0;
+ for (n = 0; n < 10; n++) battery_analog += battery_analog_sample[n];
+ battery_analog = battery_analog / 10;
+ battery_analog_array[0] = battery_analog;
+ if (battery_analog_array[9] > 0 ) {
+ battery_analog = 0;
+ for (n = 0; n < 10; n++) battery_analog += battery_analog_array[n];
+ battery_analog = battery_analog / 10;
+ }
+ battery_count ++;
+ }
+ else if (battery_count < BATTERY_CHECK) battery_count++;
+ else if (battery_count >= BATTERY_CHECK) battery_count = 0;
+
+ if (battery_analog_last != battery_analog) {
+ battery_analog_last = battery_analog;
+ MenuFunctions::battery2();
+ }
+ }
+}
+void MenuFunctions::battery2(bool initial)
+{
+ uint16_t the_color;
+ if ( digitalRead(CHARGING_PIN) == 1) the_color = TFT_BLUE;
+ else if (battery_analog < 20) the_color = TFT_RED;
+ else if (battery_analog < 40) the_color = TFT_YELLOW;
+ else the_color = TFT_GREEN;
+
+ display_obj.tft.setTextColor(the_color, STATUSBAR_COLOR);
+ display_obj.tft.fillRect(SB_TOUCH_X, 0, 50, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+ display_obj.tft.drawXBitmap(SB_TOUCH_X,
+ 0,
+ menu_icons[STATUS_BAT],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ the_color);
+ display_obj.tft.drawString((String) battery_analog + "%", SB_BAT_X, 0, 2);
+}
+#else
+void MenuFunctions::battery(bool initial)
+{
+ #ifdef HAS_BATTERY
+ uint16_t the_color;
+ if (battery_obj.i2c_supported)
+ {
+ // Could use int compare maybe idk
+ if (((String)battery_obj.battery_level != "25") && ((String)battery_obj.battery_level != "0"))
+ the_color = TFT_GREEN;
+ else
+ the_color = TFT_RED;
+
+ if ((battery_obj.battery_level != battery_obj.old_level) || (initial)) {
+ battery_obj.old_level = battery_obj.battery_level;
+ display_obj.tft.fillRect(204, 0, SCREEN_WIDTH, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+ }
+
+ display_obj.tft.setCursor(0, 1);
+ /*if (!this->disable_touch) {
+ display_obj.tft.drawXBitmap(SB_TOUCH_X,
+ 0,
+ menu_icons[STATUS_BAT],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ the_color);
+ }*/
+ #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+ display_obj.tft.drawString((String)battery_obj.battery_level + "%", SB_BAT_X, 0, 1);
+ #else
+ display_obj.tft.drawString((String)battery_obj.battery_level + "%", SB_BAT_X, 0, 2);
+ #endif
+ }
+ #endif
+}
+void MenuFunctions::battery2(bool initial)
+{
+ MenuFunctions::battery(initial);
+}
+#endif
+
+void MenuFunctions::updateStatusBar()
+{
+ display_obj.tft.setTextSize(1);
+
+ bool status_changed = false;
+
+ #if defined(MARAUDER_MINI) || defined(MARAUDER_M5STICKC) || defined(MARAUDER_REV_FEATHER) || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) || defined(MARAUDER_MINI_V3)
+ display_obj.tft.setFreeFont(NULL);
+ #endif
+
+ uint16_t the_color;
+
+ #ifdef HAS_GPS
+ if (this->old_gps_sat_count != gps_obj.getNumSats()) {
+ this->old_gps_sat_count = gps_obj.getNumSats();
+ display_obj.tft.fillRect(0, 0, SCREEN_WIDTH, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+ status_changed = true;
+ }
+ #endif
+
+ // GPS Stuff
+ #ifdef HAS_GPS
+ if (gps_obj.getGpsModuleStatus()) {
+ if (gps_obj.getFixStatus())
+ the_color = TFT_GREEN;
+ else
+ the_color = TFT_RED;
+
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(4,
+ 0,
+ menu_icons[STATUS_GPS],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ the_color);
+ display_obj.tft.setTextColor(TFT_WHITE, STATUSBAR_COLOR, true);
+
+ display_obj.tft.drawString(gps_obj.getNumSatsString(), 22, 0, 2);
+ #elif defined(HAS_SCREEN)
+ display_obj.tft.setTextColor(the_color, STATUSBAR_COLOR, true);
+ display_obj.tft.drawString("GPS", 0, 0, 1);
+ #endif
+ }
+ #endif
+
+ display_obj.tft.setTextColor(TFT_WHITE, STATUSBAR_COLOR, true);
+
+ // WiFi Channel Stuff
+ uint8_t primaryChannel;
+ wifi_second_chan_t secondChannel;
+ esp_err_t err = esp_wifi_get_channel(&primaryChannel, &secondChannel);
+
+ uint8_t current_channel = wifi_scan_obj.set_channel;
+
+ if (err == ESP_OK)
+ current_channel = primaryChannel;
+
+ if ((current_channel != wifi_scan_obj.old_channel) || (status_changed)) {
+ wifi_scan_obj.old_channel = current_channel;
+ #if defined(MARAUDER_MINI) || defined(MARAUDER_M5STICKC) || defined(MARAUDER_REV_FEATHER) || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) || defined(MARAUDER_MINI_V3)
+ display_obj.tft.fillRect(TFT_WIDTH/4, 0, CHAR_WIDTH * 6, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+ #elif defined(HAS_DUAL_BAND)
+ display_obj.tft.fillRect(50, 0, (CHAR_WIDTH / 2) * 8, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+ #else
+ display_obj.tft.fillRect(50, 0, (CHAR_WIDTH / 2) * 7, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+ #endif
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawString("CH: " + (String)wifi_scan_obj.old_channel, 50, 0, 2);
+ #endif
+
+ #ifdef HAS_MINI_SCREEN
+ display_obj.tft.drawString("CH:" + (String)wifi_scan_obj.old_channel, TFT_WIDTH/4, 0, 1);
+ #endif
+ }
+
+ // RAM Stuff
+ wifi_scan_obj.free_ram = String(esp_get_free_heap_size());
+ if ((wifi_scan_obj.free_ram != wifi_scan_obj.old_free_ram) || (status_changed)) {
+ wifi_scan_obj.old_free_ram = wifi_scan_obj.free_ram;
+ //display_obj.tft.fillRect(SB_MEM_X, 0, 60, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+ #ifdef HAS_FULL_SCREEN
+ #ifndef HAS_PSRAM
+ display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", SB_MEM_X, 0, 2);
+ #else
+ display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", SB_MEM_X, 0, 1);
+ display_obj.tft.drawString("P:" + String(getPSRAMUsagePercent()) + "%", SB_MEM_X, 8, 1);
+ #endif
+ #endif
+
+ #ifdef HAS_MINI_SCREEN
+ display_obj.tft.drawString(String(getDRAMUsagePercent()) + "%", TFT_WIDTH/1.75, 0, 1);
+ #endif
+ }
+
+ // Draw battery info
+ MenuFunctions::battery(false);
+ display_obj.tft.fillRect(186, 0, 16, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+
+ // Disable touch stuff
+ #ifdef HAS_ILI9341
+ #ifdef HAS_BUTTONS
+ if (this->disable_touch) {
+ display_obj.tft.setCursor(0, 1);
+ display_obj.tft.drawXBitmap(SB_TOUCH_X,
+ 0,
+ menu_icons[DISABLE_TOUCH],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_RED);
+ }
+ else {
+ display_obj.tft.setCursor(0, 1);
+ display_obj.tft.drawXBitmap(SB_TOUCH_X,
+ 0,
+ menu_icons[DISABLE_TOUCH],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_DARKGREY);
+ }
+ #endif
+ #endif
+
+ // Draw SD info
+ #ifdef HAS_SD
+ if (sd_obj.supported)
+ the_color = TFT_GREEN;
+ else
+ the_color = TFT_RED;
+
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(SB_SD_X,
+ 0,
+ menu_icons[STATUS_SD],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ the_color);
+ #endif
+ #endif
+
+ #ifdef HAS_MINI_SCREEN
+ display_obj.tft.setTextColor(the_color, STATUSBAR_COLOR, true);
+ display_obj.tft.drawString("SD", TFT_WIDTH - 12, 0, 1);
+ #endif
+
+ // WiFi connection status stuff
+ if (wifi_scan_obj.wifi_connected) {
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(SB_WIFI_X,
+ 0,
+ menu_icons[JOINED],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_GREEN);
+ #endif
+ } else {
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(SB_WIFI_X,
+ 0,
+ menu_icons[JOINED],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_DARKGREY);
+ #endif
+ }
+
+ // Force PMKID stuff
+ if ((wifi_scan_obj.force_pmkid) || (wifi_scan_obj.ep_deauth)) {
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(SB_FORCE_X,
+ 0,
+ menu_icons[FORCE],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_GREEN);
+ #endif
+ } else {
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(SB_FORCE_X,
+ 0,
+ menu_icons[FORCE],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_DARKGREY);
+ #endif
+ }
+}
+
+void MenuFunctions::drawStatusBar()
+{
+ display_obj.tft.setTextSize(1);
+ #ifdef HAS_MINI_SCREEN
+ display_obj.tft.setFreeFont(NULL);
+ #endif
+ display_obj.tft.fillRect(0, 0, SCREEN_WIDTH, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+ display_obj.tft.setTextColor(TFT_WHITE, STATUSBAR_COLOR);
+
+ uint16_t the_color;
+
+ // GPS Stuff
+ #ifdef HAS_GPS
+ if (gps_obj.getGpsModuleStatus()) {
+ if (gps_obj.getFixStatus())
+ the_color = TFT_GREEN;
+ else
+ the_color = TFT_RED;
+
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(4,
+ 0,
+ menu_icons[STATUS_GPS],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ the_color);
+ display_obj.tft.setTextColor(TFT_WHITE, STATUSBAR_COLOR);
+
+ display_obj.tft.drawString(gps_obj.getNumSatsString(), 22, 0, 2);
+ #endif
+ }
+ #endif
+
+ display_obj.tft.setTextColor(TFT_WHITE, STATUSBAR_COLOR);
+
+
+ // WiFi Channel Stuff
+ uint8_t primaryChannel;
+ wifi_second_chan_t secondChannel;
+ esp_err_t err = esp_wifi_get_channel(&primaryChannel, &secondChannel);
+
+ if (err == ESP_OK)
+ wifi_scan_obj.old_channel = primaryChannel;
+ else
+ wifi_scan_obj.old_channel = wifi_scan_obj.set_channel;
+
+ #ifdef HAS_MINI_SCREEN
+ display_obj.tft.fillRect(43, 0, TFT_WIDTH * 0.21, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+ #else
+ display_obj.tft.fillRect(50, 0, TFT_WIDTH * 0.21, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+ #endif
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawString("CH: " + (String)wifi_scan_obj.old_channel, 50, 0, 2);
+ #endif
+
+ #ifdef HAS_MINI_SCREEN
+ display_obj.tft.drawString("CH:" + (String)wifi_scan_obj.old_channel, TFT_WIDTH/4, 0, 1);
+ #endif
+
+ // RAM Stuff
+ wifi_scan_obj.free_ram = String(esp_get_free_heap_size());
+ wifi_scan_obj.old_free_ram = wifi_scan_obj.free_ram;
+ display_obj.tft.fillRect(100, 0, 60, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+ #ifdef HAS_FULL_SCREEN
+ #ifndef HAS_PSRAM
+ display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", SB_MEM_X, 0, 2);
+ #else
+ display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", SB_MEM_X, 0, 1);
+ display_obj.tft.drawString("P:" + String(getPSRAMUsagePercent()) + "%", SB_MEM_X, 8, 1);
+ #endif
+ #endif
+
+ #ifdef HAS_MINI_SCREEN
+ display_obj.tft.drawString(String(getDRAMUsagePercent()) + "%", TFT_WIDTH/1.75, 0, 1);
+ #endif
+
+
+ MenuFunctions::battery(true);
+ display_obj.tft.fillRect(186, 0, 16, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
+
+
+ // Disable touch stuff
+ #ifdef HAS_ILI9341
+ #ifdef HAS_BUTTONS
+ if (this->disable_touch) {
+ display_obj.tft.setCursor(0, 1);
+ display_obj.tft.drawXBitmap(SB_TOUCH_X,
+ 0,
+ menu_icons[DISABLE_TOUCH],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_RED);
+ }
+ else {
+ display_obj.tft.setCursor(0, 1);
+ display_obj.tft.drawXBitmap(SB_TOUCH_X,
+ 0,
+ menu_icons[DISABLE_TOUCH],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_DARKGREY);
+ }
+ #endif
+ #endif
+
+ // Draw SD info
+ #ifdef HAS_SD
+ if (sd_obj.supported)
+ the_color = TFT_GREEN;
+ else
+ the_color = TFT_RED;
+
+
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(SB_SD_X,
+ 0,
+ menu_icons[STATUS_SD],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ the_color);
+ #endif
+ #endif
+
+ #ifdef HAS_MINI_SCREEN
+ display_obj.tft.setTextColor(the_color, STATUSBAR_COLOR);
+ display_obj.tft.drawString("SD", TFT_WIDTH - 12, 0, 1);
+ #endif
+
+ // WiFi connection status stuff
+ if (wifi_scan_obj.wifi_connected) {
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(SB_WIFI_X,
+ 0,
+ menu_icons[JOINED],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_GREEN);
+ #endif
+ } else {
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(SB_WIFI_X,
+ 0,
+ menu_icons[JOINED],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_DARKGREY);
+ #endif
+ }
+
+ // Force PMKID stuff
+ if ((wifi_scan_obj.force_pmkid) || (wifi_scan_obj.ep_deauth)) {
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(SB_FORCE_X,
+ 0,
+ menu_icons[FORCE],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_GREEN);
+ #endif
+ } else {
+ #ifdef HAS_FULL_SCREEN
+ display_obj.tft.drawXBitmap(SB_FORCE_X,
+ 0,
+ menu_icons[FORCE],
+ 16,
+ 16,
+ STATUSBAR_COLOR,
+ TFT_DARKGREY);
+ #endif
+ }
+}
+
+void MenuFunctions::orientDisplay() {
+ display_obj.init();
+
+ display_obj.tft.setRotation(SCREEN_ORIENTATION); // Portrait
+
+ display_obj.tft.setCursor(0, 0);
+
+ #ifdef HAS_ILI9341
+ #ifndef HAS_CYD_TOUCH
+ display_obj.setCalData();
+ #else
+ display_obj.touchscreen.setRotation(0);
+ #endif
+ #endif
+
+ changeMenu(current_menu, true);
+}
+
+const char* MenuFunctions::callSetting(const char* key) {
+ specSettingMenu.name = key;
+
+ const char* setting_type = settings_obj.getSettingType(key);
+
+ if (setting_type && strcmp(setting_type, "bool") == 0) {
+ return "bool";
+ }
+
+ return "";
+}
+
+/*void MenuFunctions::displaySetting(String key, Menu* menu, int index) {
+ specSettingMenu.name = key;
+
+ bool setting_value = settings_obj.loadSetting(key);
+
+ // Make a local copy of menu node
+ MenuNode node = menu->list->get(index);
+
+ display_obj.tft.setTextWrap(false);
+ display_obj.tft.setFreeFont(NULL);
+ display_obj.tft.setCursor(0, 100);
+ display_obj.tft.setTextSize(1);
+
+ // Set local copy value
+ if (!setting_value) {
+ display_obj.tft.setTextColor(TFT_RED);
+ display_obj.tft.println(F(text_table1[4]));
+ node.selected = false;
+ }
+ else {
+ display_obj.tft.setTextColor(TFT_GREEN);
+ display_obj.tft.println(F(text_table1[5]));
+ node.selected = true;
+ }
+
+ // Put local copy back into menu
+ menu->list->set(index, node);
+
+}*/
+
+void MenuFunctions::displaySetting(const char* key, Menu* menu, int index) {
+ specSettingMenu.name = String(key);
+
+ bool setting_value = settings_obj.loadSetting(key);
+
+ // Make a local copy of menu node
+ MenuNode node = menu->list->get(index);
+
+ display_obj.tft.setTextWrap(false);
+ display_obj.tft.setFreeFont(NULL);
+ display_obj.tft.setCursor(0, 100);
+ display_obj.tft.setTextSize(1);
+
+ // Set local copy value
+ if (!setting_value) {
+ display_obj.tft.setTextColor(TFT_RED);
+ display_obj.tft.println(F(text_table1[4]));
+ node.selected = false;
+ } else {
+ display_obj.tft.setTextColor(TFT_GREEN);
+ display_obj.tft.println(F(text_table1[5]));
+ node.selected = true;
+ }
+
+ // Put local copy back into menu
+ menu->list->set(index, node);
+}
+
+#if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)
+void MenuFunctions::updateKeyboard()
+{
+ M5CardputerKeyboard.updateKeyList();
+ M5CardputerKeyboard.updateKeysState();
+}
+
+bool MenuFunctions::isKeyPressed(char c)
+{
+ bool pressed = M5CardputerKeyboard.isKeyPressed(c);
+
+ if (pressed)
+ delay(200);
+
+ return pressed;
+}
+#endif
+
+#ifdef HAS_DIRECT_UPLOAD
+ void MenuFunctions::buildUploadFileMenu() {
+ if (sd_obj.supported) {
+ this->setupSDFileList();
+
+ uploadLogsMenu.list->clear();
+ delete uploadLogsMenu.list;
+ uploadLogsMenu.list = new LinkedList();
+ uploadLogsMenu.name = "Logs";
+
+ uploadLogsMenu.parentMenu = &wifiGeneralMenu;
+
+ this->addNodes(&uploadLogsMenu, "Back", TFTLIGHTGREY, 0, [this]() {
+ this->changeMenu(uploadLogsMenu.parentMenu, true);
+ });
+
+ this->addNodes(&uploadLogsMenu, "Delete Wardrive Logs", TFTORANGE, 0, [this]() {
+ this->changeMenu(&deleteAllMenu, true);
+ });
+
+ this->addNodes(&uploadLogsMenu, "Upload All", TFTGREEN, 0, [this]() {
+ this->changeMenu(&uploadAllMenu, true);
+
+ });
+
+ for (int i = 0; i < sd_obj.sd_files->size(); i++) {
+ File current_file = sd_obj.getFile("/" + sd_obj.sd_files->get(i));
+ if (sd_obj.sd_files->get(i).startsWith("wardrive_") || sd_obj.sd_files->get(i).startsWith("wigle-")) {
+ if (!sd_obj.sd_files->get(i).endsWith(".wdg") && !sd_obj.sd_files->get(i).endsWith(".wigle") && !sd_obj.sd_files->get(i).endsWith(".gpx")) {
+ this->addNodes(&uploadLogsMenu, sd_obj.sd_files->get(i).c_str(), TFTCYAN, 0, [this, i]() {
+ sd_obj.selected_file_name = sd_obj.sd_files->get(i);
+ Serial.println(sd_obj.sd_files->get(i) + " selected");
+ this->changeMenu(&actionMenu, true);
+ });
+ }
+ }
+ }
+
+ Serial.println("Built SD file menu with " + (String)sd_obj.sd_files->size() + " files");
+ } else {
+ Serial.println("SD Card not detected. Skipping menu creation...");
+ }
+ }
#endif
const char* MenuFunctions::foxSortLabel() const {
@@ -1786,2933 +1786,2933 @@ void MenuFunctions::buildBluetoothFoxHuntMenu() {
// Function to build the menus
void MenuFunctions::RunSetup()
-{
- extern LinkedList* access_points;
- extern LinkedList