Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f623880772 | ||
|
|
ec3ca6d0ad | ||
|
|
59b143fb3e | ||
|
|
c5136b5d2e | ||
|
|
ba05c388b1 | ||
|
|
a98be0d435 | ||
|
|
da43c8b369 | ||
|
|
7a5134bb86 | ||
|
|
bbc10e4452 | ||
|
|
f05776ba45 | ||
|
|
20694f593a | ||
|
|
140451b47c | ||
|
|
6490a12b30 | ||
|
|
1a4136137d | ||
|
|
e79db36906 | ||
|
|
d9d25b0010 | ||
|
|
8a18e55bb7 | ||
|
|
1c86a71704 | ||
|
|
f7db1ea401 | ||
|
|
bdc209d489 | ||
|
|
cc891457ce | ||
|
|
6c3a0d30b7 | ||
|
|
12182af21c | ||
|
|
c9c6bbf971 | ||
|
|
7391a05c8a | ||
|
|
dd6f800b48 | ||
|
|
6f2c2862f6 |
49
.travis.yml
@@ -11,24 +11,6 @@ env:
|
||||
|
||||
before_install:
|
||||
|
||||
# TODO: undo
|
||||
# remove submodules, we don't want those to be actually tested for compliance
|
||||
- git submodule status | rm -Rf `cut -d ' ' -f 3`
|
||||
|
||||
# Formatting checks:
|
||||
# Check for files starting with a blank line
|
||||
- find . -path './.git' -prune -or -type f -print0 | xargs -0 -L1 bash -c 'head -1 "$0" | grep --binary-files=without-match --regexp="^$"; if [[ "$?" == "0" ]]; then echo "Blank line found at start of $0."; false; fi'
|
||||
# Check for tabs
|
||||
- find . -path './.git' -prune -or -type f \( ! -iname ".gitmodules" \) -exec grep --with-filename --line-number --binary-files=without-match --regexp=$'\t' '{}' \; -exec echo 'Tab found.' \; -exec false '{}' +
|
||||
# Check for trailing whitespace
|
||||
- find . -path './.git' -prune -or -type f -exec grep --with-filename --line-number --binary-files=without-match --regexp='[[:blank:]]$' '{}' \; -exec echo 'Trailing whitespace found.' \; -exec false '{}' +
|
||||
# Check for non-Unix line endings
|
||||
- find . -path './.git' -prune -or -type f -exec grep --files-with-matches --binary-files=without-match --regexp=$'\r$' '{}' \; -exec echo 'Non-Unix EOL detected.' \; -exec false '{}' +
|
||||
# Check for blank lines at end of files
|
||||
- find . -path './.git' -prune -or -type f -print0 | xargs -0 -L1 bash -c 'tail -1 "$0" | grep --binary-files=without-match --regexp="^$"; if [[ "$?" == "0" ]]; then echo "Blank line found at end of $0."; false; fi'
|
||||
# Check for files that don't end in a newline (https://stackoverflow.com/a/25686825)
|
||||
- find . -path './.git' -prune -or -type f -print0 | xargs -0 -L1 bash -c 'if test "$(grep --files-with-matches --binary-files=without-match --max-count=1 --regexp='.*' "$0")" && test "$(tail --bytes=1 "$0")"; then echo "No new line at end of $0."; false; fi'
|
||||
|
||||
- git clone https://github.com/per1234/arduino-ci-script.git "${HOME}/scripts/arduino-ci-script"
|
||||
- cd "${HOME}/scripts/arduino-ci-script"
|
||||
# Get new tags from the remote
|
||||
@@ -46,19 +28,23 @@ before_install:
|
||||
- set_application_folder "$APPLICATION_FOLDER"
|
||||
- set_sketchbook_folder "$SKETCHBOOK_FOLDER"
|
||||
|
||||
- install_ide '("1.8.0" "1.8.9" "newest")'
|
||||
#- install_ide '("1.8.11" "1.8.12" "newest")'
|
||||
- install_ide '("newest")'
|
||||
|
||||
# Install the library from the repository
|
||||
- install_library
|
||||
- install_library "M5Stack"
|
||||
- install_library 'https://github.com/bblanchon/ArduinoJson.git' # "ArduinoJSON"
|
||||
|
||||
- ls ${TRAVIS_BUILD_DIR} -la
|
||||
- ls ${TRAVIS_BUILD_DIR}/examples/M5Stack-SD-Menu/ -la
|
||||
- ls $SKETCHBOOK_FOLDER -la
|
||||
- ls $SKETCHBOOK_FOLDER/libraries -la
|
||||
- pwd
|
||||
# what the fsck is wrong install_package() ??
|
||||
#- install_library "https://github.com/lvgl/lv_port_esp32/archive/master.zip"
|
||||
- install_library "TFT_eSPI"
|
||||
- install_library "JPEGDecoder"
|
||||
- install_library "LinkedList"
|
||||
- install_library "lv_arduino"
|
||||
- install_library "https://github.com/adafruit/Adafruit_NeoPixel/archive/1.5.0.zip" ## "Adafruit_NeoPixel"
|
||||
- install_library 'https://github.com/bblanchon/ArduinoJson/releases/download/v5.13.5/ArduinoJson-v5.13.5.zip'
|
||||
- install_library 'https://github.com/h2zero/NimBLE-Arduino/archive/master.zip' # NimBLE
|
||||
|
||||
- cp ${TRAVIS_BUILD_DIR}/User_Setup.h /home/travis/arduino-sketchbook/libraries/TFT_eSPI/User_Setup.h
|
||||
#- install_library 'https://github.com/bblanchon/ArduinoJson.git'
|
||||
#- install_library "https://github.com/spacehuhn/SimpleList.git"
|
||||
#
|
||||
- install_package "esp32:esp32" "https://dl.espressif.com/dl/package_esp32_index.json" # # esp32:esp32:m5stack-core-esp32
|
||||
#- /home/travis/arduino-ide/arduino-1.8.10/arduino --pref "compiler.warning_level=none" --save-prefs &>/dev/null
|
||||
#- /home/travis/arduino-ide/arduino-1.8.10/arduino --pref "build.warn_data_percentage=75" --save-prefs &>/dev/null
|
||||
@@ -69,8 +55,9 @@ before_install:
|
||||
script:
|
||||
# Compile all example sketches included with the library
|
||||
# build_sketch arguments: sketch name, fqbn, allow failure, IDE version/list/range
|
||||
- check_library_manager_compliance "$TRAVIS_BUILD_DIR"
|
||||
- build_sketch "${TRAVIS_BUILD_DIR}/examples/M5Stack-SD-Menu/M5Stack-SD-Menu.ino" "esp32:esp32:m5stack-core-esp32:FlashFreq=80,UploadSpeed=921600" "false" "newest"
|
||||
# - check_library_manager_compliance "$TRAVIS_BUILD_DIR"
|
||||
- set_ide_preference "compiler.warning_level=auto"
|
||||
- build_sketch "${TRAVIS_BUILD_DIR}/esp32_marauder/esp32_marauder.ino" "esp32:esp32:d32_pro:FlashFreq=80,UploadSpeed=921600,PartitionScheme=min_spiffs" "false" "newest"
|
||||
|
||||
after_script:
|
||||
# Commit a report of the job results to the CI-reports repository
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 11 and column 76.
|
21
README.md
@@ -3,7 +3,7 @@
|
||||
<!---[](https://travis-ci.com/justcallmekoko/ESP32Marauder)--->
|
||||
<!---Shields/Badges https://shields.io/--->
|
||||
|
||||
# ESP32 Marauder v0.6.4
|
||||
# ESP32 Marauder v0.7.0
|
||||
<p align="center"><img alt="Marauder logo" src="https://github.com/justcallmekoko/ESP32Marauder/blob/master/pictures/marauder3L.jpg?raw=true" width="300"></p>
|
||||
<p align="center">
|
||||
<b>A suite of WiFi/Bluetooth offensive and defensive tools for the ESP32</b>
|
||||
@@ -18,6 +18,9 @@
|
||||
<a href="https://www.tindie.com/products/justcallmekoko/esp32-marauder/"><img src="https://d2ss6ovg47m0r5.cloudfront.net/badges/tindie-larges.png" alt="I sell on Tindie" width="200" height="104"></a>
|
||||
</p>
|
||||
|
||||
[](http://hits.dwyl.io/justcallmekoko/badges)
|
||||
[](https://travis-ci.com/justcallmekoko/ESP32Marauder)
|
||||
|
||||
# Table Of Condensation
|
||||
- [About](#about)
|
||||
- [YouTube](#youtube)
|
||||
@@ -63,6 +66,7 @@ You can check out the marauder article written [here](https://www.hackster.io/ne
|
||||
- Save PCAP files to SD card
|
||||
|
||||
# Do It Yourself
|
||||
<p align="center"><img alt="Marauder logo" src="https://github.com/justcallmekoko/ESP32Marauder/blob/master/pictures/diy.png?raw=true" width="800"></p>
|
||||
|
||||
## Hardware
|
||||
This project requires the following hardware in order to work:
|
||||
@@ -92,6 +96,14 @@ Make the following connections between your 2.8" TFT Screen and your ESP32 board
|
||||
| | T_IRQ | |
|
||||
| SD_CS | | GPIO12 |
|
||||
|
||||
For the analog battery circuit, use a 4 to 1 voltage divider, and (optional) a mosfet.
|
||||
For the charge detection circuit, use a 1 to 2 voltage divider (the charge detection is optional and only changes the battery icon colour while charging)
|
||||
| BATTERY | ESP32 |
|
||||
| ------- | ------ |
|
||||
| BAT + | GPIO34 |
|
||||
| MOSFET | GPIO13 |
|
||||
| CHARGE +| GPIO27 |
|
||||
|
||||
## Flashing Firmware
|
||||
### Using Arduino IDE
|
||||
1. Install the [Arduino IDE](https://www.arduino.cc/en/main/software)
|
||||
@@ -111,11 +123,18 @@ Make the following connections between your 2.8" TFT Screen and your ESP32 board
|
||||
8. Install the [CH340 Drivers](https://github.com/justcallmekoko/ESP32Marauder/blob/master/Drivers/CH34x_Install_Windows_v3_4.EXE)
|
||||
9. Download or clone this repository
|
||||
10. Open `esp32_marauder.ino`
|
||||
10.5. If you're using the analog battery measuring circuit, go to the MenuFunctions.h and change "#define BATTERY_ANALOG_ON" to 1
|
||||
11. Plug your ESP32 into a USB port and select the COM port under `Tools`>`Port`
|
||||
12. Select `LOLIN D32` under `Tools`>`Boards`
|
||||
12.5 If you want an upscaled version of the logo, go to the data folder and rename "marauder3L1.jpg" to "marauder3L.jpg"
|
||||
13. Click `ESP32 Sketch Data Upload` and wait for the SPIFFS upload to finish
|
||||
14. Click the upload button
|
||||
|
||||
<p align="center">
|
||||
<img alt="Marauder logo" src="https://raw.githubusercontent.com/justcallmekoko/ESP32Marauder/master/pictures/m5stack.jpg?raw=true" height="300">
|
||||
<img alt="Marauder logo" src="https://github.com/justcallmekoko/ESP32Marauder/blob/master/pictures/odroid_marauder.jpg?raw=true" height="300">
|
||||
</p>
|
||||
|
||||
## Updating Firmware
|
||||
There are multiple options available to update the Marauder firmware. If you have already built the project from this repo, you can just pull the latest commit and flash the firmware using the Arduino IDE (see [here](#using-arduino-ide)).
|
||||
If you own an ESP32 Marauder (v0.4.0 or later) and have not build the project, you can follow [these instructions](#web-update) for installing the latest update over the air via Marauder's web interface or [these instructions](#sd-update) for installing the latest update using an SD Card.
|
||||
|
||||
@@ -3,6 +3,56 @@
|
||||
|
||||
#define jquery_min_js_v3_2_1_gz_len 30178
|
||||
|
||||
PROGMEM static String espressif_macs[] = {
|
||||
"fc:f5:c4",
|
||||
"f4:cf:a2",
|
||||
"f0:08:d1",
|
||||
"ec:fa:bc",
|
||||
"e0:98:06",
|
||||
"dc:4f:22",
|
||||
"d8:f1:5b",
|
||||
"d8:bf:c0",
|
||||
"d8:a0:1d",
|
||||
"cc:50:e3",
|
||||
"c8:2b:96",
|
||||
"c4:4f:33",
|
||||
"bc:dd:c2",
|
||||
"b8:f0:09",
|
||||
"b4:e6:2d",
|
||||
"ac:d0:74",
|
||||
"ac:67:b2",
|
||||
"a4:cf:12",
|
||||
"a4:7b:9d",
|
||||
"a0:20:a6",
|
||||
"98:f4:ab",
|
||||
"90:97:d5",
|
||||
"8c:aa:b5",
|
||||
"84:f3:eb",
|
||||
"84:cc:a8",
|
||||
"84:0d:8e",
|
||||
"80:7d:3a",
|
||||
"7c:df:a1",
|
||||
"7c:9e:bd",
|
||||
"70:03:9f",
|
||||
"68:c6:3a",
|
||||
"60:01:94",
|
||||
"5c:cf:7f",
|
||||
"54:5a:a6",
|
||||
"50:02:91",
|
||||
"4c:11:ae",
|
||||
"48:3f:da",
|
||||
"40:f5:20",
|
||||
"3c:71:bf",
|
||||
"30:ae:a4",
|
||||
"2c:f4:32",
|
||||
"2c:3a:e8",
|
||||
"24:b2:de",
|
||||
"24:6f:28",
|
||||
"24:62:ab",
|
||||
"24:0a:c4",
|
||||
"18:fe:34",
|
||||
"10:52:1c"
|
||||
};
|
||||
|
||||
|
||||
PROGMEM static const unsigned char menu_icons[][66] = {
|
||||
@@ -143,7 +193,19 @@ PROGMEM static const unsigned char menu_icons[][66] = {
|
||||
0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0xFF, 0xFF},
|
||||
{0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFC, 0x07, 0xF8, 0x07, 0xF0, 0x07, 0xE0, // SD: 23
|
||||
0x67, 0xE7, 0x97, 0xE9, 0x17, 0xE9, 0x67, 0xE9, 0x87, 0xE9, 0x97, 0xE9,
|
||||
0x67, 0xE7, 0x07, 0xE0, 0x07, 0xE0, 0xFF, 0xFF}
|
||||
0x67, 0xE7, 0x07, 0xE0, 0x07, 0xE0, 0xFF, 0xFF},
|
||||
{0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0x3F, 0x7F, 0x80, 0x3F, 0xBF, 0x7F, 0x3F, // PWNAGOTCHI: 24
|
||||
0xDF, 0xC0, 0x3E, 0x6F, 0xBF, 0x3D, 0xBF, 0x61, 0x3F, 0xFF, 0xDE, 0x3F,
|
||||
0xFF, 0xF3, 0x3F, 0xFF, 0xFF, 0x3F, 0xFB, 0xFF, 0x37, 0xFD, 0xFF, 0x2F,
|
||||
0xFE, 0xFF, 0x1F, 0x8E, 0x7F, 0x1C, 0x36, 0xBF, 0x19, 0x16, 0xBF, 0x18,
|
||||
0x06, 0x3F, 0x18, 0x8E, 0x7F, 0x1C, 0xFD, 0xFF, 0x2F, 0xDB, 0xF3, 0x36,
|
||||
0x3F, 0x0C, 0x3F, 0xFF, 0xFF, 0x3F},
|
||||
{0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0x3F, 0xFF, 0xC7, 0x3F, 0x7F, 0x0E, 0x3F, // ESPRESSIF: 25
|
||||
0x2F, 0x30, 0x3E, 0x37, 0x40, 0x3C, 0xF3, 0x83, 0x38, 0x0B, 0x04, 0x39,
|
||||
0x03, 0x18, 0x32, 0x01, 0x20, 0x32, 0xF1, 0x21, 0x34, 0x01, 0x46, 0x34,
|
||||
0x03, 0x84, 0x38, 0x7B, 0x88, 0x38, 0x93, 0x88, 0x38, 0x17, 0x89, 0x3C,
|
||||
0x07, 0x89, 0x3F, 0xCF, 0x89, 0x3D, 0x9F, 0x49, 0x3C, 0x7F, 0x00, 0x3F,
|
||||
0xFF, 0xE3, 0x3F, 0xFF, 0xFF, 0x3F}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -7,6 +7,10 @@ Big thanks to bodmer for having great TFT and JPEG libraries
|
||||
https://github.com/bodmer
|
||||
*/
|
||||
|
||||
//PROGMEM lv_obj_t * slider_label;
|
||||
//PROGMEM lv_obj_t * ta1;
|
||||
//PROGMEM lv_obj_t * ta2;
|
||||
|
||||
Display::Display()
|
||||
{
|
||||
}
|
||||
@@ -54,16 +58,85 @@ void Display::RunSetup()
|
||||
|
||||
|
||||
// Draw the title screen
|
||||
drawJpeg("/marauder3L.jpg", 0 , 0); // 240 x 320 image
|
||||
//drawJpeg("/marauder3L.jpg", 0 , 0); // 240 x 320 image
|
||||
|
||||
//showCenterText(version_number, 250);
|
||||
tft.drawCentreString(version_number, 120, 250, 2);
|
||||
//tft.drawCentreString(version_number, 120, 250, 2);
|
||||
|
||||
digitalWrite(TFT_BL, HIGH);
|
||||
//digitalWrite(TFT_BL, HIGH);
|
||||
|
||||
delay(5000);
|
||||
//delay(5000);
|
||||
}
|
||||
|
||||
/* Interrupt driven periodic handler */
|
||||
/*
|
||||
void Display::lv_tick_handler()
|
||||
{
|
||||
lv_tick_inc(LVGL_TICK_PERIOD);
|
||||
}*/
|
||||
|
||||
/* Display flushing */
|
||||
/*void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
|
||||
{
|
||||
extern Display display_obj;
|
||||
uint16_t c;
|
||||
|
||||
display_obj.tft.startWrite();
|
||||
display_obj.tft.setAddrWindow(area->x1, area->y1, (area->x2 - area->x1 + 1), (area->y2 - area->y1 + 1));
|
||||
for (int y = area->y1; y <= area->y2; y++) {
|
||||
for (int x = area->x1; x <= area->x2; x++) {
|
||||
c = color_p->full;
|
||||
display_obj.tft.writeColor(c, 1);
|
||||
color_p++;
|
||||
}
|
||||
}
|
||||
display_obj.tft.endWrite();
|
||||
lv_disp_flush_ready(disp);
|
||||
}*/
|
||||
|
||||
/*
|
||||
bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data)
|
||||
{
|
||||
extern Display display_obj;
|
||||
|
||||
uint16_t touchX, touchY;
|
||||
|
||||
bool touched = display_obj.tft.getTouch(&touchX, &touchY, 600);
|
||||
|
||||
if(!touched)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(touchX>WIDTH_1 || touchY > HEIGHT_1)
|
||||
{
|
||||
Serial.println("Y or y outside of expected parameters..");
|
||||
Serial.print("y:");
|
||||
Serial.print(touchX);
|
||||
Serial.print(" x:");
|
||||
Serial.print(touchY);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
data->state = touched ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
|
||||
|
||||
//if(data->state == LV_INDEV_STATE_PR) touchpad_get_xy(&last_x, &last_y);
|
||||
|
||||
data->point.x = touchX;
|
||||
data->point.y = touchY;
|
||||
|
||||
Serial.print("Data x");
|
||||
Serial.println(touchX);
|
||||
|
||||
Serial.print("Data y");
|
||||
Serial.println(touchY);
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}*/
|
||||
|
||||
void Display::tftDrawGraphObjects(byte x_scale)
|
||||
{
|
||||
//draw the graph objects
|
||||
@@ -389,6 +462,15 @@ void Display::drawJpeg(const char *filename, int xpos, int ypos) {
|
||||
}
|
||||
}
|
||||
|
||||
void Display::setupDraw() {
|
||||
this->tft.drawLine(0, 0, 10, 0, TFT_MAGENTA);
|
||||
this->tft.drawLine(0, 0, 0, 10, TFT_GREEN);
|
||||
this->tft.drawLine(0, 0, 0, 0, TFT_CYAN);
|
||||
}
|
||||
|
||||
uint16_t xlast;
|
||||
uint16_t ylast;
|
||||
uint32_t AH;
|
||||
void Display::drawStylus()
|
||||
{
|
||||
uint16_t x = 0, y = 0; // To store the touch coordinates
|
||||
@@ -396,13 +478,61 @@ void Display::drawStylus()
|
||||
// Pressed will be set true is there is a valid touch on the screen
|
||||
boolean pressed = tft.getTouch(&x, &y);
|
||||
|
||||
if ((x <= 10) && (y <= 10) && (pressed)) {
|
||||
Serial.println("Exit draw function");
|
||||
this->draw_tft = false;
|
||||
this->exit_draw = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw a white spot at the detected coordinates
|
||||
if (pressed) {
|
||||
tft.fillCircle(x, y, 2, TFT_WHITE);
|
||||
// tft.fillCircle(x, y, 2, TFT_WHITE);
|
||||
if ( xlast > 0 && ylast > 0 ) {
|
||||
uint16_t the_color = TFT_WHITE;
|
||||
uint16_t wd = 1;
|
||||
int xlast2;
|
||||
int ylast2;
|
||||
int x2;
|
||||
int y2;
|
||||
int n;
|
||||
int n2 = -wd;
|
||||
xlast2 = xlast - wd;
|
||||
x2 = x - wd;
|
||||
for (n = -wd; n <= wd; n++) {
|
||||
ylast2 = ylast + n;
|
||||
y2 = y + n;
|
||||
tft.drawLine(xlast2, ylast2, x2, y2, the_color);
|
||||
}
|
||||
for (n2 = -wd; n2 <= wd; n2++) {
|
||||
xlast2 = xlast + n2;
|
||||
x2 = x + n2;
|
||||
tft.drawLine(xlast2, ylast2, x2, y2, the_color);
|
||||
}
|
||||
for (n = wd; n >= -wd; n--) {
|
||||
ylast2 = ylast + n;
|
||||
y2 = y + n;
|
||||
tft.drawLine(xlast2, ylast2, x2, y2, the_color);
|
||||
}
|
||||
for (n2 = wd; n2 >= -wd; n2--) {
|
||||
xlast2 = xlast + n2;
|
||||
x2 = x + n2;
|
||||
tft.drawLine(xlast2, ylast2, x2, y2, the_color);
|
||||
}
|
||||
// tft.drawLine(xlast, ylast, x, y, TFT_WHITE);
|
||||
}
|
||||
xlast = x;
|
||||
ylast = y;
|
||||
AH = 0;
|
||||
//Serial.print("x,y = ");
|
||||
//Serial.print(x);
|
||||
//Serial.print(",");
|
||||
//Serial.println(y);
|
||||
} else if ( AH < 5 ) {
|
||||
AH++;
|
||||
} else if ( AH == 5 ) {
|
||||
xlast = 0;
|
||||
ylast = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -686,8 +816,111 @@ void Display::buildBanner(String msg, int xpos)
|
||||
img.print(msg);
|
||||
}
|
||||
|
||||
/*
|
||||
void Display::initLVGL() {
|
||||
tick.attach_ms(LVGL_TICK_PERIOD, lv_tick_handler);
|
||||
|
||||
lv_init();
|
||||
|
||||
lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10);
|
||||
|
||||
lv_disp_drv_t disp_drv;
|
||||
lv_disp_drv_init(&disp_drv);
|
||||
disp_drv.hor_res = WIDTH_1;
|
||||
disp_drv.ver_res = HEIGHT_1;
|
||||
disp_drv.flush_cb = my_disp_flush;
|
||||
disp_drv.buffer = &disp_buf;
|
||||
lv_disp_drv_register(&disp_drv);
|
||||
|
||||
lv_indev_drv_t indev_drv;
|
||||
lv_indev_drv_init(&indev_drv);
|
||||
indev_drv.type = LV_INDEV_TYPE_POINTER;
|
||||
indev_drv.read_cb = my_touchpad_read;
|
||||
lv_indev_drv_register(&indev_drv);
|
||||
}*/
|
||||
|
||||
/*
|
||||
void Display::deinitLVGL() {
|
||||
lv_deinit();
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
void Display::joinWiFiGFX(){
|
||||
|
||||
// Create one text area
|
||||
ta1 = lv_textarea_create(lv_scr_act(), NULL);
|
||||
lv_textarea_set_one_line(ta1, true);
|
||||
lv_obj_set_width(ta1, LV_HOR_RES / 2 - 20);
|
||||
lv_obj_set_pos(ta1, 5, 20);
|
||||
//lv_ta_set_cursor_type(ta, LV_CURSOR_BLOCK);
|
||||
lv_textarea_set_text(ta1, "");
|
||||
lv_obj_set_event_cb(ta1, ta_event_cb);
|
||||
|
||||
// Create first label
|
||||
lv_obj_t * ssid_label = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_label_set_text(ssid_label, "SSID:");
|
||||
lv_obj_align(ssid_label, ta1, LV_ALIGN_OUT_TOP_LEFT, 0, 0);
|
||||
|
||||
// Create second text area
|
||||
ta2 = lv_textarea_create(lv_scr_act(), ta1);
|
||||
lv_textarea_set_pwd_mode(ta2, true);
|
||||
lv_textarea_set_pwd_show_time(ta2, 1000);
|
||||
lv_textarea_set_cursor_hidden(ta2, true);
|
||||
lv_obj_align(ta2, NULL, LV_ALIGN_IN_TOP_RIGHT, -5, 20);
|
||||
|
||||
// Create second label
|
||||
lv_obj_t * pw_label = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_label_set_text(pw_label, "Password:");
|
||||
lv_obj_align(pw_label, ta2, LV_ALIGN_OUT_TOP_LEFT, 0, 0);
|
||||
|
||||
// Create a keyboard and apply the styles
|
||||
kb = lv_keyboard_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_size(kb, LV_HOR_RES, LV_VER_RES / 2);
|
||||
lv_obj_set_event_cb(kb, keyboard_event_cb);
|
||||
|
||||
// Focus it on one of the text areas to start
|
||||
lv_keyboard_set_textarea(kb, ta1);
|
||||
lv_keyboard_set_cursor_manage(kb, true);
|
||||
|
||||
}*/
|
||||
|
||||
/*
|
||||
void keyboard_event_cb(lv_obj_t * keyboard, lv_event_t event){
|
||||
lv_keyboard_def_event_cb(kb, event);
|
||||
if(event == LV_EVENT_APPLY){
|
||||
printf("LV_EVENT_APPLY\n");
|
||||
//String ta1_text = lv_textarea_get_text(lv_keyboard_get_textarea(kb));
|
||||
String ta1_text = lv_textarea_get_text(ta1);
|
||||
String ta2_text = lv_textarea_get_text(ta2);
|
||||
Serial.println(ta1_text);
|
||||
Serial.println(ta2_text);
|
||||
//joinWiFi(ta1_text, ta2_text);
|
||||
}else if(event == LV_EVENT_CANCEL){
|
||||
printf("LV_EVENT_CANCEL\n");
|
||||
lv_textarea_set_text(lv_keyboard_get_textarea(kb), "");
|
||||
}
|
||||
}*/
|
||||
|
||||
/*
|
||||
void ta_event_cb(lv_obj_t * ta, lv_event_t event)
|
||||
{
|
||||
if(event == LV_EVENT_CLICKED) {
|
||||
if(kb != NULL)
|
||||
lv_keyboard_set_textarea(kb, ta);
|
||||
}
|
||||
|
||||
//else if(event == LV_EVENT_INSERT) {
|
||||
// const char * str = lv_event_get_data();
|
||||
// if(str[0] == '\n') {
|
||||
// printf("Ready\n");
|
||||
// }
|
||||
//}
|
||||
}*/
|
||||
|
||||
void Display::main()
|
||||
{
|
||||
//lv_task_handler();
|
||||
return;
|
||||
}
|
||||
// End SPIFFS_functions
|
||||
|
||||
@@ -8,13 +8,16 @@
|
||||
//#include <SimpleList.h>
|
||||
#include <LinkedList.h>
|
||||
#include <SPI.h>
|
||||
//#include <lvgl.h>
|
||||
#include <Ticker.h>
|
||||
//#include <M5Stack.h>
|
||||
#include "SPIFFS.h"
|
||||
#include "Assets.h"
|
||||
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
#define TFT_SHIELD
|
||||
//#define TFT_DIY
|
||||
//#define TFT_SHIELD
|
||||
#define TFT_DIY
|
||||
|
||||
#define SCREEN_WIDTH 240
|
||||
#define SCREEN_HEIGHT 320
|
||||
@@ -33,9 +36,21 @@
|
||||
//#define MENU_FONT &FreeSansBold9pt7b
|
||||
#define BUTTON_ARRAY_LEN 7
|
||||
#define STATUS_BAR_WIDTH 16
|
||||
//#define LVGL_TICK_PERIOD 6
|
||||
|
||||
#define STATUSBAR_COLOR 0x4A49
|
||||
|
||||
//PROGMEM void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p);
|
||||
//PROGMEM bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data);
|
||||
|
||||
//PROGMEM static lv_disp_buf_t disp_buf;
|
||||
//PROGMEM static lv_color_t buf[LV_HOR_RES_MAX * 10];
|
||||
|
||||
//PROGMEM static void ta_event_cb(lv_obj_t * ta, lv_event_t event);
|
||||
//PROGMEM static void keyboard_event_cb(lv_obj_t * keyboard, lv_event_t event);
|
||||
|
||||
// lvgl stuff
|
||||
//PROGMEM static lv_obj_t *kb;
|
||||
|
||||
class Display
|
||||
{
|
||||
@@ -53,18 +68,21 @@ class Display
|
||||
//void addNodes(Menu* menu, String name, Menu* child, std::function<void()> callable);
|
||||
//void changeMenu(Menu* menu);
|
||||
//void showMenuList(Menu* menu, int layer);
|
||||
//static void lv_tick_handler();
|
||||
|
||||
public:
|
||||
Display();
|
||||
Ticker tick;
|
||||
TFT_eSPI tft = TFT_eSPI();
|
||||
TFT_eSprite img = TFT_eSprite(&tft);
|
||||
TFT_eSPI_Button key[BUTTON_ARRAY_LEN];
|
||||
String version_number = "v0.6.5";
|
||||
String version_number = "v0.7.0";
|
||||
|
||||
bool printing = false;
|
||||
bool loading = false;
|
||||
bool tteBar = false;
|
||||
bool draw_tft = false;
|
||||
bool exit_draw = false;
|
||||
|
||||
int TOP_FIXED_AREA_2 = 48;
|
||||
int print_delay_1, print_delay_2 = 10;
|
||||
@@ -94,6 +112,9 @@ class Display
|
||||
// We can speed up scrolling of short text lines by just blanking the character we drew
|
||||
int blank[19]; // We keep all the strings pixel lengths to optimise the speed of the top line blanking
|
||||
|
||||
//void initLVGL();
|
||||
//void deinitLVGL();
|
||||
//void joinWiFiGFX();
|
||||
void tftDrawGraphObjects(byte x_scale);
|
||||
void tftDrawEapolColorKey();
|
||||
void tftDrawColorKey();
|
||||
@@ -105,6 +126,7 @@ class Display
|
||||
void clearScreen();
|
||||
void displayBuffer(bool do_clear = false);
|
||||
void drawJpeg(const char *filename, int xpos, int ypos);
|
||||
void setupDraw();
|
||||
void drawStylus();
|
||||
void getTouchWhileFunction(bool pressed);
|
||||
void initScrollValues(bool tte = false);
|
||||
|
||||
@@ -6,12 +6,13 @@ LedInterface::LedInterface() {
|
||||
|
||||
void LedInterface::RunSetup() {
|
||||
Serial.println("Setting neopixel to black...");
|
||||
strip.setBrightness(0);
|
||||
strip.begin();
|
||||
strip.setBrightness(50);
|
||||
strip.setPixelColor(0, strip.Color(0, 0, 0));
|
||||
strip.show();
|
||||
delay(100);
|
||||
strip.setPixelColor(0, strip.Color(255, 0, 0));
|
||||
strip.setBrightness(50);
|
||||
strip.setPixelColor(0, strip.Color(0, 0, 0));
|
||||
strip.show();
|
||||
this->initTime = millis();
|
||||
}
|
||||
|
||||
@@ -10,8 +10,12 @@ MenuFunctions::MenuFunctions()
|
||||
// Function to check menu input
|
||||
void MenuFunctions::main(uint32_t currentTime)
|
||||
{
|
||||
if (display_obj.exit_draw) {
|
||||
display_obj.exit_draw = false;
|
||||
changeMenu(current_menu);
|
||||
}
|
||||
if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) ||
|
||||
(wifi_scan_obj.currentScanMode == OTA_UPDATE) ||
|
||||
(wifi_scan_obj.currentScanMode == OTA_UPDATE) ||
|
||||
(wifi_scan_obj.currentScanMode == SHOW_INFO)) {
|
||||
if (wifi_scan_obj.orient_display) {
|
||||
this->orientDisplay();
|
||||
@@ -32,7 +36,7 @@ void MenuFunctions::main(uint32_t currentTime)
|
||||
}
|
||||
|
||||
//this->displayCurrentMenu();
|
||||
|
||||
|
||||
boolean pressed = false;
|
||||
// This is code from bodmer's keypad example
|
||||
uint16_t t_x = 0, t_y = 0; // To store the touch coordinates
|
||||
@@ -42,7 +46,7 @@ void MenuFunctions::main(uint32_t currentTime)
|
||||
(wifi_scan_obj.currentScanMode != WIFI_ATTACK_BEACON_SPAM) &&
|
||||
(wifi_scan_obj.currentScanMode != WIFI_ATTACK_RICK_ROLL))
|
||||
display_obj.displayBuffer();
|
||||
//Serial.println(wifi_scan_obj.freeRAM());
|
||||
//Serial.println(wifi_scan_obj.freeRAM());
|
||||
|
||||
|
||||
// Pressed will be set true is there is a valid touch on the screen
|
||||
@@ -60,29 +64,31 @@ void MenuFunctions::main(uint32_t currentTime)
|
||||
//Serial.print(millis() - pre_getTouch);
|
||||
//Serial.println("ms");
|
||||
|
||||
|
||||
|
||||
// This is if there are scans/attacks going on
|
||||
if ((wifi_scan_obj.currentScanMode != WIFI_SCAN_OFF) &&
|
||||
(pressed) &&
|
||||
if ((wifi_scan_obj.currentScanMode != WIFI_SCAN_OFF) &&
|
||||
(pressed) &&
|
||||
(wifi_scan_obj.currentScanMode != OTA_UPDATE) &&
|
||||
(wifi_scan_obj.currentScanMode != SHOW_INFO))
|
||||
{
|
||||
{
|
||||
// Stop the current scan
|
||||
if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) ||
|
||||
(wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
|
||||
(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_RICK_ROLL) ||
|
||||
(wifi_scan_obj.currentScanMode == BT_SCAN_ALL) ||
|
||||
(wifi_scan_obj.currentScanMode == BT_SCAN_SKIMMERS))
|
||||
(wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) ||
|
||||
(wifi_scan_obj.currentScanMode == WIFI_SCAN_PWN) ||
|
||||
(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_RICK_ROLL) ||
|
||||
(wifi_scan_obj.currentScanMode == BT_SCAN_ALL) ||
|
||||
(wifi_scan_obj.currentScanMode == BT_SCAN_SKIMMERS))
|
||||
{
|
||||
Serial.println("Stopping scan...");
|
||||
wifi_scan_obj.StartScan(WIFI_SCAN_OFF);
|
||||
|
||||
|
||||
// If we don't do this, the text and button coordinates will be off
|
||||
display_obj.tft.init();
|
||||
|
||||
|
||||
// Take us back to the menu
|
||||
changeMenu(current_menu);
|
||||
}
|
||||
@@ -92,7 +98,7 @@ void MenuFunctions::main(uint32_t currentTime)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Check if any key coordinate boxes contain the touch coordinates
|
||||
// This is for when on a menu
|
||||
if ((wifi_scan_obj.currentScanMode != WIFI_ATTACK_BEACON_SPAM) &&
|
||||
@@ -106,7 +112,7 @@ void MenuFunctions::main(uint32_t currentTime)
|
||||
display_obj.key[b].press(false); // tell the button it is NOT pressed
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check if any key has changed state
|
||||
for (uint8_t b = 0; b < current_menu->list->size(); b++) {
|
||||
display_obj.tft.setFreeFont(MENU_FONT);
|
||||
@@ -115,17 +121,17 @@ void MenuFunctions::main(uint32_t currentTime)
|
||||
//display_obj.key[b].drawButton(ML_DATUM, BUTTON_PADDING, current_menu->list->get(b).name, true);
|
||||
display_obj.key[b].drawButton(true, current_menu->list->get(b).name);
|
||||
if (current_menu->list->get(b).name != "Back")
|
||||
display_obj.tft.drawXBitmap(0,
|
||||
KEY_Y + b * (KEY_H + KEY_SPACING_Y) - (ICON_H / 2),
|
||||
menu_icons[current_menu->list->get(b).icon],
|
||||
ICON_W,
|
||||
ICON_H,
|
||||
current_menu->list->get(b).color,
|
||||
TFT_BLACK);
|
||||
display_obj.tft.drawXBitmap(0,
|
||||
KEY_Y + b * (KEY_H + KEY_SPACING_Y) - (ICON_H / 2),
|
||||
menu_icons[current_menu->list->get(b).icon],
|
||||
ICON_W,
|
||||
ICON_H,
|
||||
current_menu->list->get(b).color,
|
||||
TFT_BLACK);
|
||||
}
|
||||
//else if (pressed)
|
||||
// display_obj.key[b].drawButton(false, current_menu->list->get(b).name);
|
||||
|
||||
|
||||
// If button was just release, execute the button's function
|
||||
if ((display_obj.key[b].justReleased()) && (!pressed))
|
||||
{
|
||||
@@ -134,19 +140,19 @@ void MenuFunctions::main(uint32_t currentTime)
|
||||
display_obj.key[b].drawButton(false, current_menu->list->get(b).name);
|
||||
current_menu->list->get(b).callable();
|
||||
}
|
||||
// This
|
||||
// This
|
||||
else if ((display_obj.key[b].justReleased()) && (pressed)) {
|
||||
display_obj.key[b].drawButton(false, current_menu->list->get(b).name);
|
||||
if (current_menu->list->get(b).name != "Back")
|
||||
display_obj.tft.drawXBitmap(0,
|
||||
KEY_Y + b * (KEY_H + KEY_SPACING_Y) - (ICON_H / 2),
|
||||
menu_icons[current_menu->list->get(b).icon],
|
||||
ICON_W,
|
||||
ICON_H,
|
||||
TFT_BLACK,
|
||||
display_obj.tft.drawXBitmap(0,
|
||||
KEY_Y + b * (KEY_H + KEY_SPACING_Y) - (ICON_H / 2),
|
||||
menu_icons[current_menu->list->get(b).icon],
|
||||
ICON_W,
|
||||
ICON_H,
|
||||
TFT_BLACK,
|
||||
current_menu->list->get(b).color);
|
||||
}
|
||||
|
||||
|
||||
display_obj.tft.setFreeFont(NULL);
|
||||
}
|
||||
}
|
||||
@@ -154,9 +160,109 @@ void MenuFunctions::main(uint32_t currentTime)
|
||||
y = -1;
|
||||
}
|
||||
|
||||
void MenuFunctions::updateStatusBar()
|
||||
#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(186, 0, 50, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
|
||||
display_obj.tft.drawXBitmap(186,
|
||||
0,
|
||||
menu_icons[STATUS_BAT],
|
||||
16,
|
||||
16,
|
||||
STATUSBAR_COLOR,
|
||||
the_color);
|
||||
display_obj.tft.drawString((String) battery_analog + "%", 204, 0, 2);
|
||||
}
|
||||
#else
|
||||
void MenuFunctions::battery(bool initial)
|
||||
{
|
||||
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);
|
||||
display_obj.tft.drawXBitmap(186,
|
||||
0,
|
||||
menu_icons[STATUS_BAT],
|
||||
16,
|
||||
16,
|
||||
STATUSBAR_COLOR,
|
||||
the_color);
|
||||
display_obj.tft.drawString((String)battery_obj.battery_level + "%", 204, 0, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
void MenuFunctions::battery2(bool initial)
|
||||
{
|
||||
MenuFunctions::battery(initial);
|
||||
}
|
||||
#endif
|
||||
|
||||
void MenuFunctions::updateStatusBar()
|
||||
{
|
||||
uint16_t the_color;
|
||||
|
||||
// Draw temp info
|
||||
if (temp_obj.current_temp < 70)
|
||||
@@ -178,41 +284,36 @@ void MenuFunctions::updateStatusBar()
|
||||
}
|
||||
display_obj.tft.setTextColor(TFT_WHITE, STATUSBAR_COLOR);
|
||||
|
||||
// Draw battery info
|
||||
if (battery_obj.i2c_supported)
|
||||
{
|
||||
if ((String)battery_obj.battery_level != "25")
|
||||
the_color = TFT_GREEN;
|
||||
else
|
||||
the_color = TFT_RED;
|
||||
|
||||
if (battery_obj.battery_level != battery_obj.old_level) {
|
||||
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);
|
||||
display_obj.tft.drawXBitmap(186,
|
||||
0,
|
||||
menu_icons[STATUS_BAT],
|
||||
16,
|
||||
16,
|
||||
STATUSBAR_COLOR,
|
||||
the_color);
|
||||
display_obj.tft.drawString((String)battery_obj.battery_level + "%", 204, 0, 2);
|
||||
}
|
||||
// WiFi Channel Stuff
|
||||
if (wifi_scan_obj.set_channel != wifi_scan_obj.old_channel) {
|
||||
wifi_scan_obj.old_channel = wifi_scan_obj.set_channel;
|
||||
display_obj.tft.fillRect(50, 0, 50, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
|
||||
display_obj.tft.drawString("CH: " + (String)wifi_scan_obj.set_channel, 50, 0, 2);
|
||||
}
|
||||
|
||||
// RAM Stuff
|
||||
wifi_scan_obj.freeRAM();
|
||||
if (wifi_scan_obj.free_ram != wifi_scan_obj.old_free_ram) {
|
||||
wifi_scan_obj.old_free_ram = wifi_scan_obj.free_ram;
|
||||
display_obj.tft.fillRect(100, 0, 60, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
|
||||
display_obj.tft.drawString((String)wifi_scan_obj.free_ram + "B", 100, 0, 2);
|
||||
}
|
||||
|
||||
// Draw battery info
|
||||
MenuFunctions::battery(false);
|
||||
|
||||
// Draw SD info
|
||||
if (sd_obj.supported)
|
||||
the_color = TFT_GREEN;
|
||||
else
|
||||
the_color = TFT_RED;
|
||||
|
||||
display_obj.tft.drawXBitmap(170,
|
||||
0,
|
||||
menu_icons[STATUS_SD],
|
||||
16,
|
||||
16,
|
||||
STATUSBAR_COLOR,
|
||||
display_obj.tft.drawXBitmap(170,
|
||||
0,
|
||||
menu_icons[STATUS_SD],
|
||||
16,
|
||||
16,
|
||||
STATUSBAR_COLOR,
|
||||
the_color);
|
||||
//display_obj.tft.print((String)battery_obj.battery_level + "%");
|
||||
}
|
||||
@@ -244,26 +345,20 @@ void MenuFunctions::drawStatusBar()
|
||||
display_obj.tft.drawString((String)temp_obj.current_temp + " C", 4, 0, 2);
|
||||
display_obj.tft.setTextColor(TFT_WHITE, STATUSBAR_COLOR);
|
||||
|
||||
// Draw battery info
|
||||
if (battery_obj.i2c_supported)
|
||||
{
|
||||
if ((String)battery_obj.battery_level != "25")
|
||||
the_color = TFT_GREEN;
|
||||
else
|
||||
the_color = TFT_RED;
|
||||
|
||||
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);
|
||||
display_obj.tft.drawXBitmap(186,
|
||||
0,
|
||||
menu_icons[STATUS_BAT],
|
||||
16,
|
||||
16,
|
||||
STATUSBAR_COLOR,
|
||||
the_color);
|
||||
display_obj.tft.drawString((String)battery_obj.battery_level + "%", 204, 0, 2);
|
||||
}
|
||||
// WiFi Channel Stuff
|
||||
wifi_scan_obj.old_channel = wifi_scan_obj.set_channel;
|
||||
display_obj.tft.fillRect(50, 0, 50, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
|
||||
display_obj.tft.drawString("CH: " + (String)wifi_scan_obj.set_channel, 50, 0, 2);
|
||||
|
||||
// RAM Stuff
|
||||
wifi_scan_obj.freeRAM();
|
||||
wifi_scan_obj.old_free_ram = wifi_scan_obj.free_ram;
|
||||
display_obj.tft.fillRect(100, 0, 60, STATUS_BAR_WIDTH, STATUSBAR_COLOR);
|
||||
display_obj.tft.drawString((String)wifi_scan_obj.free_ram + "B", 100, 0, 2);
|
||||
|
||||
|
||||
MenuFunctions::battery2(true);
|
||||
|
||||
// Draw SD info
|
||||
if (sd_obj.supported)
|
||||
@@ -271,12 +366,12 @@ void MenuFunctions::drawStatusBar()
|
||||
else
|
||||
the_color = TFT_RED;
|
||||
|
||||
display_obj.tft.drawXBitmap(170,
|
||||
0,
|
||||
menu_icons[STATUS_SD],
|
||||
16,
|
||||
16,
|
||||
STATUSBAR_COLOR,
|
||||
display_obj.tft.drawXBitmap(170,
|
||||
0,
|
||||
menu_icons[STATUS_SD],
|
||||
16,
|
||||
16,
|
||||
STATUSBAR_COLOR,
|
||||
the_color);
|
||||
//display_obj.tft.print((String)battery_obj.battery_level + "%");
|
||||
}
|
||||
@@ -284,7 +379,7 @@ void MenuFunctions::drawStatusBar()
|
||||
void MenuFunctions::orientDisplay()
|
||||
{
|
||||
display_obj.tft.init();
|
||||
|
||||
|
||||
display_obj.tft.setRotation(0); // Portrait
|
||||
|
||||
display_obj.tft.setCursor(0, 0);
|
||||
@@ -292,14 +387,14 @@ void MenuFunctions::orientDisplay()
|
||||
//uint16_t calData[5] = { 275, 3494, 361, 3528, 4 }; // tft.setRotation(0); // Portrait
|
||||
//uint16_t calData[5] = { 339, 3470, 237, 3438, 2 }; // tft.setRotation(0); // Portrait with DIY TFT
|
||||
|
||||
#ifdef TFT_SHIELD
|
||||
uint16_t calData[5] = { 275, 3494, 361, 3528, 4 }; // tft.setRotation(0); // Portrait with TFT Shield
|
||||
Serial.println("Using TFT Shield");
|
||||
#else if defined(TFT_DIY)
|
||||
uint16_t calData[5] = { 339, 3470, 237, 3438, 2 }; // tft.setRotation(0); // Portrait with DIY TFT
|
||||
Serial.println("Using TFT DIY");
|
||||
#endif
|
||||
|
||||
#ifdef TFT_SHIELD
|
||||
uint16_t calData[5] = { 275, 3494, 361, 3528, 4 }; // tft.setRotation(0); // Portrait with TFT Shield
|
||||
Serial.println("Using TFT Shield");
|
||||
#else if defined(TFT_DIY)
|
||||
uint16_t calData[5] = { 339, 3470, 237, 3438, 2 }; // tft.setRotation(0); // Portrait with DIY TFT
|
||||
Serial.println("Using TFT DIY");
|
||||
#endif
|
||||
|
||||
display_obj.tft.setTouch(calData);
|
||||
|
||||
//display_obj.clearScreen();
|
||||
@@ -355,91 +450,209 @@ void MenuFunctions::RunSetup()
|
||||
|
||||
// Build Main Menu
|
||||
mainMenu.parentMenu = NULL;
|
||||
addNodes(&mainMenu, "WiFi", TFT_GREEN, NULL, WIFI, [this](){changeMenu(&wifiMenu);});
|
||||
addNodes(&mainMenu, "Bluetooth", TFT_CYAN, NULL, BLUETOOTH, [this](){changeMenu(&bluetoothMenu);});
|
||||
addNodes(&mainMenu, "General Apps", TFT_MAGENTA, NULL, GENERAL_APPS, [this](){changeMenu(&generalMenu);});
|
||||
addNodes(&mainMenu, "Device", TFT_BLUE, NULL, DEVICE, [this](){changeMenu(&deviceMenu);});
|
||||
addNodes(&mainMenu, "Reboot", TFT_LIGHTGREY, NULL, REBOOT, [](){ESP.restart();});
|
||||
addNodes(&mainMenu, "WiFi", TFT_GREEN, NULL, WIFI, [this]() {
|
||||
changeMenu(&wifiMenu);
|
||||
});
|
||||
addNodes(&mainMenu, "Bluetooth", TFT_CYAN, NULL, BLUETOOTH, [this]() {
|
||||
changeMenu(&bluetoothMenu);
|
||||
});
|
||||
addNodes(&mainMenu, "General Apps", TFT_MAGENTA, NULL, GENERAL_APPS, [this]() {
|
||||
changeMenu(&generalMenu);
|
||||
});
|
||||
addNodes(&mainMenu, "Device", TFT_BLUE, NULL, DEVICE, [this]() {
|
||||
changeMenu(&deviceMenu);
|
||||
});
|
||||
addNodes(&mainMenu, "Reboot", TFT_LIGHTGREY, NULL, REBOOT, []() {
|
||||
ESP.restart();
|
||||
});
|
||||
|
||||
// Build WiFi Menu
|
||||
wifiMenu.parentMenu = &mainMenu; // Main Menu is second menu parent
|
||||
addNodes(&wifiMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this](){changeMenu(wifiMenu.parentMenu);});
|
||||
addNodes(&wifiMenu, "Sniffers", TFT_YELLOW, NULL, SNIFFERS, [this](){changeMenu(&wifiSnifferMenu);});
|
||||
addNodes(&wifiMenu, "Scanners", TFT_ORANGE, NULL, SCANNERS, [this](){changeMenu(&wifiScannerMenu);});
|
||||
addNodes(&wifiMenu, "Attacks", TFT_RED, NULL, ATTACKS, [this](){changeMenu(&wifiAttackMenu);});
|
||||
addNodes(&wifiMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this]() {
|
||||
changeMenu(wifiMenu.parentMenu);
|
||||
});
|
||||
addNodes(&wifiMenu, "Sniffers", TFT_YELLOW, NULL, SNIFFERS, [this]() {
|
||||
changeMenu(&wifiSnifferMenu);
|
||||
});
|
||||
addNodes(&wifiMenu, "Scanners", TFT_ORANGE, NULL, SCANNERS, [this]() {
|
||||
changeMenu(&wifiScannerMenu);
|
||||
});
|
||||
addNodes(&wifiMenu, "Attacks", TFT_RED, NULL, ATTACKS, [this]() {
|
||||
changeMenu(&wifiAttackMenu);
|
||||
});
|
||||
|
||||
// Build WiFi sniffer Menu
|
||||
wifiSnifferMenu.parentMenu = &wifiMenu; // Main Menu is second menu parent
|
||||
addNodes(&wifiSnifferMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this](){changeMenu(wifiSnifferMenu.parentMenu);});
|
||||
addNodes(&wifiSnifferMenu, "Probe Request Sniff", TFT_CYAN, NULL, PROBE_SNIFF, [this](){display_obj.clearScreen(); this->drawStatusBar(); wifi_scan_obj.StartScan(WIFI_SCAN_PROBE, TFT_CYAN);});
|
||||
addNodes(&wifiSnifferMenu, "Beacon Sniff", TFT_MAGENTA, NULL, BEACON_SNIFF, [this](){display_obj.clearScreen(); this->drawStatusBar(); wifi_scan_obj.StartScan(WIFI_SCAN_AP, TFT_MAGENTA);});
|
||||
addNodes(&wifiSnifferMenu, "Deauth Sniff", TFT_RED, NULL, DEAUTH_SNIFF, [this](){display_obj.clearScreen(); this->drawStatusBar(); wifi_scan_obj.StartScan(WIFI_SCAN_DEAUTH, TFT_RED);});
|
||||
addNodes(&wifiSnifferMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this]() {
|
||||
changeMenu(wifiSnifferMenu.parentMenu);
|
||||
});
|
||||
addNodes(&wifiSnifferMenu, "Probe Request Sniff", TFT_CYAN, NULL, PROBE_SNIFF, [this]() {
|
||||
display_obj.clearScreen();
|
||||
this->drawStatusBar();
|
||||
wifi_scan_obj.StartScan(WIFI_SCAN_PROBE, TFT_CYAN);
|
||||
});
|
||||
addNodes(&wifiSnifferMenu, "Beacon Sniff", TFT_MAGENTA, NULL, BEACON_SNIFF, [this]() {
|
||||
display_obj.clearScreen();
|
||||
this->drawStatusBar();
|
||||
wifi_scan_obj.StartScan(WIFI_SCAN_AP, TFT_MAGENTA);
|
||||
});
|
||||
addNodes(&wifiSnifferMenu, "Deauth Sniff", TFT_RED, NULL, DEAUTH_SNIFF, [this]() {
|
||||
display_obj.clearScreen();
|
||||
this->drawStatusBar();
|
||||
wifi_scan_obj.StartScan(WIFI_SCAN_DEAUTH, TFT_RED);
|
||||
});
|
||||
|
||||
// Build WiFi scanner Menu
|
||||
wifiScannerMenu.parentMenu = &wifiMenu; // Main Menu is second menu parent
|
||||
addNodes(&wifiScannerMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this](){changeMenu(wifiScannerMenu.parentMenu);});
|
||||
addNodes(&wifiScannerMenu, "Packet Monitor", TFT_BLUE, NULL, PACKET_MONITOR, [this](){wifi_scan_obj.StartScan(WIFI_PACKET_MONITOR, TFT_BLUE);});
|
||||
addNodes(&wifiScannerMenu, "EAPOL/PMKID Scan", TFT_VIOLET, NULL, EAPOL, [this](){wifi_scan_obj.StartScan(WIFI_SCAN_EAPOL, TFT_VIOLET);});
|
||||
|
||||
addNodes(&wifiScannerMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this]() {
|
||||
changeMenu(wifiScannerMenu.parentMenu);
|
||||
});
|
||||
addNodes(&wifiScannerMenu, "Packet Monitor", TFT_BLUE, NULL, PACKET_MONITOR, [this]() {
|
||||
wifi_scan_obj.StartScan(WIFI_PACKET_MONITOR, TFT_BLUE);
|
||||
});
|
||||
addNodes(&wifiScannerMenu, "EAPOL/PMKID Scan", TFT_VIOLET, NULL, EAPOL, [this]() {
|
||||
wifi_scan_obj.StartScan(WIFI_SCAN_EAPOL, TFT_VIOLET);
|
||||
});
|
||||
addNodes(&wifiScannerMenu, "Detect Pwnagotchi", TFT_RED, NULL, PWNAGOTCHI, [this]() {
|
||||
display_obj.clearScreen();
|
||||
this->drawStatusBar();
|
||||
wifi_scan_obj.StartScan(WIFI_SCAN_PWN, TFT_RED);
|
||||
});
|
||||
addNodes(&wifiScannerMenu, "Detect Espressif", TFT_ORANGE, NULL, ESPRESSIF, [this]() {
|
||||
display_obj.clearScreen();
|
||||
this->drawStatusBar();
|
||||
wifi_scan_obj.StartScan(WIFI_SCAN_ESPRESSIF, TFT_ORANGE);
|
||||
});
|
||||
|
||||
// Build WiFi attack menu
|
||||
wifiAttackMenu.parentMenu = &wifiMenu; // Main Menu is second menu parent
|
||||
addNodes(&wifiAttackMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this](){changeMenu(wifiAttackMenu.parentMenu);});
|
||||
addNodes(&wifiAttackMenu, "Beacon Spam Random", TFT_ORANGE, NULL, BEACON_SPAM, [this](){display_obj.clearScreen(); this->drawStatusBar(); wifi_scan_obj.StartScan(WIFI_ATTACK_BEACON_SPAM, TFT_ORANGE);});
|
||||
addNodes(&wifiAttackMenu, "Rick Roll Beacon", TFT_YELLOW, NULL, RICK_ROLL, [this](){display_obj.clearScreen(); this->drawStatusBar(); wifi_scan_obj.StartScan(WIFI_ATTACK_RICK_ROLL, TFT_YELLOW);});
|
||||
|
||||
addNodes(&wifiAttackMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this]() {
|
||||
changeMenu(wifiAttackMenu.parentMenu);
|
||||
});
|
||||
addNodes(&wifiAttackMenu, "Beacon Spam Random", TFT_ORANGE, NULL, BEACON_SPAM, [this]() {
|
||||
display_obj.clearScreen();
|
||||
this->drawStatusBar();
|
||||
wifi_scan_obj.StartScan(WIFI_ATTACK_BEACON_SPAM, TFT_ORANGE);
|
||||
});
|
||||
addNodes(&wifiAttackMenu, "Rick Roll Beacon", TFT_YELLOW, NULL, RICK_ROLL, [this]() {
|
||||
display_obj.clearScreen();
|
||||
this->drawStatusBar();
|
||||
wifi_scan_obj.StartScan(WIFI_ATTACK_RICK_ROLL, TFT_YELLOW);
|
||||
});
|
||||
|
||||
// Build Bluetooth Menu
|
||||
bluetoothMenu.parentMenu = &mainMenu; // Second Menu is third menu parent
|
||||
addNodes(&bluetoothMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this](){changeMenu(bluetoothMenu.parentMenu);});
|
||||
addNodes(&bluetoothMenu, "Sniffers", TFT_YELLOW, NULL, SNIFFERS, [this](){changeMenu(&bluetoothSnifferMenu);});
|
||||
addNodes(&bluetoothMenu, "Scanners", TFT_ORANGE, NULL, SCANNERS, [this](){changeMenu(&bluetoothScannerMenu);});
|
||||
addNodes(&bluetoothMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this]() {
|
||||
changeMenu(bluetoothMenu.parentMenu);
|
||||
});
|
||||
addNodes(&bluetoothMenu, "Sniffers", TFT_YELLOW, NULL, SNIFFERS, [this]() {
|
||||
changeMenu(&bluetoothSnifferMenu);
|
||||
});
|
||||
addNodes(&bluetoothMenu, "Scanners", TFT_ORANGE, NULL, SCANNERS, [this]() {
|
||||
changeMenu(&bluetoothScannerMenu);
|
||||
});
|
||||
|
||||
// Build bluetooth sniffer Menu
|
||||
bluetoothSnifferMenu.parentMenu = &bluetoothMenu; // Second Menu is third menu parent
|
||||
addNodes(&bluetoothSnifferMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this](){changeMenu(bluetoothSnifferMenu.parentMenu);});
|
||||
addNodes(&bluetoothSnifferMenu, "Bluetooth Sniffer", TFT_GREEN, NULL, BLUETOOTH_SNIFF, [this](){display_obj.clearScreen(); this->drawStatusBar(); wifi_scan_obj.StartScan(BT_SCAN_ALL, TFT_GREEN);});
|
||||
addNodes(&bluetoothSnifferMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this]() {
|
||||
changeMenu(bluetoothSnifferMenu.parentMenu);
|
||||
});
|
||||
addNodes(&bluetoothSnifferMenu, "Bluetooth Sniffer", TFT_GREEN, NULL, BLUETOOTH_SNIFF, [this]() {
|
||||
display_obj.clearScreen();
|
||||
this->drawStatusBar();
|
||||
wifi_scan_obj.StartScan(BT_SCAN_ALL, TFT_GREEN);
|
||||
});
|
||||
|
||||
// Build bluetooth scanner Menu
|
||||
bluetoothScannerMenu.parentMenu = &bluetoothMenu; // Second Menu is third menu parent
|
||||
addNodes(&bluetoothScannerMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this](){changeMenu(bluetoothScannerMenu.parentMenu);});
|
||||
addNodes(&bluetoothScannerMenu, "Detect Card Skimmers", TFT_MAGENTA, NULL, CC_SKIMMERS, [this](){display_obj.clearScreen(); this->drawStatusBar(); wifi_scan_obj.StartScan(BT_SCAN_SKIMMERS, TFT_MAGENTA);});
|
||||
addNodes(&bluetoothScannerMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this]() {
|
||||
changeMenu(bluetoothScannerMenu.parentMenu);
|
||||
});
|
||||
addNodes(&bluetoothScannerMenu, "Detect Card Skimmers", TFT_MAGENTA, NULL, CC_SKIMMERS, [this]() {
|
||||
display_obj.clearScreen();
|
||||
this->drawStatusBar();
|
||||
wifi_scan_obj.StartScan(BT_SCAN_SKIMMERS, TFT_MAGENTA);
|
||||
});
|
||||
|
||||
// General apps menu
|
||||
generalMenu.parentMenu = &mainMenu;
|
||||
addNodes(&generalMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this](){display_obj.draw_tft = false; changeMenu(generalMenu.parentMenu);});
|
||||
addNodes(&generalMenu, "Draw", TFT_WHITE, NULL, DRAW, [this](){display_obj.clearScreen(); display_obj.draw_tft = true;});
|
||||
addNodes(&generalMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this]() {
|
||||
display_obj.draw_tft = false;
|
||||
changeMenu(generalMenu.parentMenu);
|
||||
});
|
||||
addNodes(&generalMenu, "Draw", TFT_WHITE, NULL, DRAW, [this]() {
|
||||
display_obj.clearScreen();
|
||||
display_obj.setupDraw();
|
||||
display_obj.draw_tft = true;
|
||||
});
|
||||
|
||||
// Device menu
|
||||
deviceMenu.parentMenu = &mainMenu;
|
||||
addNodes(&deviceMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this](){changeMenu(deviceMenu.parentMenu);});
|
||||
addNodes(&deviceMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this]() {
|
||||
changeMenu(deviceMenu.parentMenu);
|
||||
});
|
||||
//addNodes(&deviceMenu, "Update Firmware", TFT_ORANGE, NULL, UPDATE, [this](){wifi_scan_obj.currentScanMode = OTA_UPDATE; changeMenu(&updateMenu); web_obj.setupOTAupdate();});
|
||||
addNodes(&deviceMenu, "Update Firmware", TFT_ORANGE, NULL, UPDATE, [this](){wifi_scan_obj.currentScanMode = OTA_UPDATE; changeMenu(&whichUpdateMenu);});
|
||||
addNodes(&deviceMenu, "Device Info", TFT_WHITE, NULL, DEVICE_INFO, [this](){wifi_scan_obj.currentScanMode = SHOW_INFO; changeMenu(&infoMenu); wifi_scan_obj.RunInfo();});
|
||||
addNodes(&deviceMenu, "Update Firmware", TFT_ORANGE, NULL, UPDATE, [this]() {
|
||||
wifi_scan_obj.currentScanMode = OTA_UPDATE;
|
||||
changeMenu(&whichUpdateMenu);
|
||||
});
|
||||
addNodes(&deviceMenu, "Device Info", TFT_WHITE, NULL, DEVICE_INFO, [this]() {
|
||||
wifi_scan_obj.currentScanMode = SHOW_INFO;
|
||||
changeMenu(&infoMenu);
|
||||
wifi_scan_obj.RunInfo();
|
||||
});
|
||||
//addNodes(&deviceMenu, "Join WiFi", TFT_YELLOW, NULL, SNIFFERS, [this](){display_obj.clearScreen(); wifi_scan_obj.currentScanMode = LV_JOIN_WIFI; wifi_scan_obj.StartScan(LV_JOIN_WIFI, TFT_YELLOW);});
|
||||
|
||||
// Select update
|
||||
whichUpdateMenu.parentMenu = &deviceMenu;
|
||||
addNodes(&whichUpdateMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this](){changeMenu(whichUpdateMenu.parentMenu);});
|
||||
addNodes(&whichUpdateMenu, "Web Update", TFT_GREEN, NULL, WEB_UPDATE, [this](){wifi_scan_obj.currentScanMode = OTA_UPDATE; changeMenu(&updateMenu); web_obj.setupOTAupdate();});
|
||||
if (sd_obj.supported) addNodes(&whichUpdateMenu, "SD Update", TFT_MAGENTA, NULL, SD_UPDATE, [this](){wifi_scan_obj.currentScanMode = OTA_UPDATE; changeMenu(&confirmMenu);});
|
||||
|
||||
addNodes(&whichUpdateMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this]() {
|
||||
changeMenu(whichUpdateMenu.parentMenu);
|
||||
});
|
||||
addNodes(&whichUpdateMenu, "Web Update", TFT_GREEN, NULL, WEB_UPDATE, [this]() {
|
||||
wifi_scan_obj.currentScanMode = OTA_UPDATE;
|
||||
changeMenu(&updateMenu);
|
||||
web_obj.setupOTAupdate();
|
||||
});
|
||||
if (sd_obj.supported) addNodes(&whichUpdateMenu, "SD Update", TFT_MAGENTA, NULL, SD_UPDATE, [this]() {
|
||||
wifi_scan_obj.currentScanMode = OTA_UPDATE;
|
||||
changeMenu(&confirmMenu);
|
||||
});
|
||||
|
||||
// Confirm SD update menu
|
||||
confirmMenu.parentMenu = &whichUpdateMenu;
|
||||
addNodes(&confirmMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this](){changeMenu(confirmMenu.parentMenu);});
|
||||
addNodes(&confirmMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this]() {
|
||||
changeMenu(confirmMenu.parentMenu);
|
||||
});
|
||||
//addNodes(&confirmMenu, "Yes", TFT_ORANGE, NULL, UPDATE, [this](){wifi_scan_obj.currentScanMode = OTA_UPDATE; changeMenu(&updateMenu); sd_obj.runUpdate();});
|
||||
addNodes(&confirmMenu, "Yes", TFT_ORANGE, NULL, UPDATE, [this](){wifi_scan_obj.currentScanMode = OTA_UPDATE; changeMenu(&failedUpdateMenu); sd_obj.runUpdate();});
|
||||
|
||||
addNodes(&confirmMenu, "Yes", TFT_ORANGE, NULL, UPDATE, [this]() {
|
||||
wifi_scan_obj.currentScanMode = OTA_UPDATE;
|
||||
changeMenu(&failedUpdateMenu);
|
||||
sd_obj.runUpdate();
|
||||
});
|
||||
|
||||
// Web Update
|
||||
updateMenu.parentMenu = &deviceMenu;
|
||||
addNodes(&updateMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this](){wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF; changeMenu(updateMenu.parentMenu); WiFi.softAPdisconnect(true); web_obj.shutdownServer();});
|
||||
addNodes(&updateMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this]() {
|
||||
wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF;
|
||||
changeMenu(updateMenu.parentMenu);
|
||||
WiFi.softAPdisconnect(true);
|
||||
web_obj.shutdownServer();
|
||||
});
|
||||
//addNodes(&updateMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this](){wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF; changeMenu(updateMenu.parentMenu);});
|
||||
|
||||
// Failed update menu
|
||||
failedUpdateMenu.parentMenu = &whichUpdateMenu;
|
||||
addNodes(&failedUpdateMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this](){wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF; changeMenu(failedUpdateMenu.parentMenu);});
|
||||
|
||||
addNodes(&failedUpdateMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this]() {
|
||||
wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF;
|
||||
changeMenu(failedUpdateMenu.parentMenu);
|
||||
});
|
||||
|
||||
// Device info menu
|
||||
infoMenu.parentMenu = &deviceMenu;
|
||||
addNodes(&infoMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this](){wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF; changeMenu(infoMenu.parentMenu);});
|
||||
addNodes(&infoMenu, "Back", TFT_LIGHTGREY, NULL, 0, [this]() {
|
||||
wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF;
|
||||
changeMenu(infoMenu.parentMenu);
|
||||
});
|
||||
|
||||
// Set the current menu to the mainMenu
|
||||
changeMenu(&mainMenu);
|
||||
@@ -448,8 +661,8 @@ void MenuFunctions::RunSetup()
|
||||
}
|
||||
|
||||
// Function to change menu
|
||||
void MenuFunctions::changeMenu(Menu* menu)
|
||||
{
|
||||
void MenuFunctions::changeMenu(Menu * menu)
|
||||
{
|
||||
display_obj.initScrollValues();
|
||||
display_obj.setupScrollArea(TOP_FIXED_AREA, BOT_FIXED_AREA);
|
||||
display_obj.tft.init();
|
||||
@@ -461,7 +674,7 @@ void MenuFunctions::changeMenu(Menu* menu)
|
||||
}
|
||||
|
||||
// Function to show all MenuNodes in a Menu
|
||||
void MenuFunctions::showMenuList(Menu* menu, int layer)
|
||||
void MenuFunctions::showMenuList(Menu * menu, int layer)
|
||||
{
|
||||
// Iterate through all of the menu nodes in the menu
|
||||
for (int i = 0; i < menu->list->size(); i++)
|
||||
@@ -481,14 +694,14 @@ void MenuFunctions::showMenuList(Menu* menu, int layer)
|
||||
|
||||
|
||||
// Function to add MenuNodes to a menu
|
||||
void MenuFunctions::addNodes(Menu* menu, String name, uint16_t color, Menu* child, int place, std::function<void()> callable)
|
||||
void MenuFunctions::addNodes(Menu * menu, String name, uint16_t color, Menu * child, int place, std::function<void()> callable)
|
||||
{
|
||||
TFT_eSPI_Button new_button;
|
||||
menu->list->add(MenuNode{name, color, place, &new_button, callable});
|
||||
//strcpy(menu->list->get(-1).icon, bluetooth_icon);
|
||||
}
|
||||
|
||||
void MenuFunctions::buildButtons(Menu* menu)
|
||||
void MenuFunctions::buildButtons(Menu * menu)
|
||||
{
|
||||
Serial.println("Bulding buttons...");
|
||||
if (menu->list != NULL)
|
||||
@@ -501,17 +714,17 @@ void MenuFunctions::buildButtons(Menu* menu)
|
||||
char buf[menu->list->get(i).name.length() + 1] = {};
|
||||
menu->list->get(i).name.toCharArray(buf, menu->list->get(i).name.length() + 1);
|
||||
display_obj.key[i].initButton(&display_obj.tft,
|
||||
KEY_X + 0 * (KEY_W + KEY_SPACING_X),
|
||||
KEY_Y + i * (KEY_H + KEY_SPACING_Y), // x, y, w, h, outline, fill, text
|
||||
KEY_W,
|
||||
KEY_H,
|
||||
TFT_BLACK, // Outline
|
||||
TFT_BLACK, // Fill
|
||||
menu->list->get(i).color, // Text
|
||||
buf,
|
||||
KEY_TEXTSIZE);
|
||||
KEY_X + 0 * (KEY_W + KEY_SPACING_X),
|
||||
KEY_Y + i * (KEY_H + KEY_SPACING_Y), // x, y, w, h, outline, fill, text
|
||||
KEY_W,
|
||||
KEY_H,
|
||||
TFT_BLACK, // Outline
|
||||
TFT_BLACK, // Fill
|
||||
menu->list->get(i).color, // Text
|
||||
buf,
|
||||
KEY_TEXTSIZE);
|
||||
|
||||
display_obj.key[i].setLabelDatum(BUTTON_PADDING - (KEY_W/2), 2, ML_DATUM);
|
||||
display_obj.key[i].setLabelDatum(BUTTON_PADDING - (KEY_W / 2), 2, ML_DATUM);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -543,12 +756,12 @@ void MenuFunctions::displayCurrentMenu()
|
||||
display_obj.key[i].drawButton(false, current_menu->list->get(i).name);
|
||||
|
||||
if (current_menu->list->get(i).name != "Back")
|
||||
display_obj.tft.drawXBitmap(0,
|
||||
KEY_Y + i * (KEY_H + KEY_SPACING_Y) - (ICON_H / 2),
|
||||
menu_icons[current_menu->list->get(i).icon],
|
||||
ICON_W,
|
||||
ICON_H,
|
||||
TFT_BLACK,
|
||||
display_obj.tft.drawXBitmap(0,
|
||||
KEY_Y + i * (KEY_H + KEY_SPACING_Y) - (ICON_H / 2),
|
||||
menu_icons[current_menu->list->get(i).icon],
|
||||
ICON_W,
|
||||
ICON_H,
|
||||
TFT_BLACK,
|
||||
current_menu->list->get(i).color);
|
||||
}
|
||||
display_obj.tft.setFreeFont(NULL);
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
#ifndef MenuFunctions_h
|
||||
#define MenuFunctions_h
|
||||
|
||||
#define BATTERY_ANALOG_ON 0
|
||||
|
||||
#include "WiFiScan.h"
|
||||
#include "Display.h"
|
||||
#include "BatteryInterface.h"
|
||||
#include "SDInterface.h"
|
||||
#include "Web.h"
|
||||
|
||||
|
||||
extern Display display_obj;
|
||||
extern WiFiScan wifi_scan_obj;
|
||||
extern Web web_obj;
|
||||
@@ -28,6 +31,12 @@ extern BatteryInterface battery_obj;
|
||||
|
||||
#define FLASH_BUTTON 0
|
||||
|
||||
#if BATTERY_ANALOG_ON == 1
|
||||
#define BATTERY_PIN 13
|
||||
#define ANALOG_PIN 34
|
||||
#define CHARGING_PIN 27
|
||||
#endif
|
||||
|
||||
// Icon definitions
|
||||
#define ATTACKS 0
|
||||
#define BEACON_SNIFF 1
|
||||
@@ -53,41 +62,43 @@ extern BatteryInterface battery_obj;
|
||||
#define EAPOL 21
|
||||
#define STATUS_BAT 22
|
||||
#define STATUS_SD 23
|
||||
#define PWNAGOTCHI 24
|
||||
#define ESPRESSIF 25
|
||||
|
||||
struct Menu;
|
||||
|
||||
// Individual Nodes of a menu
|
||||
|
||||
struct MenuNode {
|
||||
String name;
|
||||
uint16_t color;
|
||||
int icon;
|
||||
TFT_eSPI_Button* button;
|
||||
std::function<void()> callable;
|
||||
String name;
|
||||
uint16_t color;
|
||||
int icon;
|
||||
TFT_eSPI_Button* button;
|
||||
std::function<void()> callable;
|
||||
};
|
||||
|
||||
// Full Menus
|
||||
struct Menu {
|
||||
String name;
|
||||
LinkedList<MenuNode>* list;
|
||||
Menu * parentMenu;
|
||||
uint8_t selected;
|
||||
String name;
|
||||
LinkedList<MenuNode>* list;
|
||||
Menu * parentMenu;
|
||||
//uint8_t selected;
|
||||
};
|
||||
|
||||
|
||||
class MenuFunctions
|
||||
{
|
||||
private:
|
||||
private:
|
||||
|
||||
String u_result = "";
|
||||
|
||||
uint32_t initTime = 0;
|
||||
|
||||
|
||||
Menu* current_menu;
|
||||
|
||||
// Main menu stuff
|
||||
Menu mainMenu;
|
||||
|
||||
|
||||
Menu wifiMenu;
|
||||
Menu bluetoothMenu;
|
||||
Menu generalMenu;
|
||||
@@ -110,17 +121,19 @@ class MenuFunctions
|
||||
Menu bluetoothScannerMenu;
|
||||
|
||||
// Menu icons
|
||||
|
||||
|
||||
|
||||
//TFT_eSPI_Button key[BUTTON_ARRAY_LEN];
|
||||
|
||||
|
||||
void addNodes(Menu* menu, String name, uint16_t color, Menu* child, int place, std::function<void()> callable);
|
||||
void drawStatusBar();
|
||||
void updateStatusBar();
|
||||
void battery(bool initial = false);
|
||||
void battery2(bool initial = false);
|
||||
void showMenuList(Menu* menu, int layer);
|
||||
void orientDisplay();
|
||||
|
||||
public:
|
||||
public:
|
||||
MenuFunctions();
|
||||
|
||||
uint16_t x = -1, y = -1;
|
||||
|
||||
@@ -43,6 +43,8 @@ void Web::onJavaScript(void) {
|
||||
|
||||
void Web::setupOTAupdate()
|
||||
{
|
||||
uint8_t newMACAddress[] = {0x06, 0x07, 0x0D, 0x09, 0x0E, 0x0D};
|
||||
|
||||
display_obj.tft.setTextWrap(false);
|
||||
display_obj.tft.setFreeFont(NULL);
|
||||
display_obj.tft.setCursor(0, 100);
|
||||
@@ -67,6 +69,7 @@ void Web::setupOTAupdate()
|
||||
Serial.println(wifi_scan_obj.freeRAM());
|
||||
|
||||
Serial.println("Starting softAP...");
|
||||
esp_wifi_set_mac(ESP_IF_WIFI_AP, &newMACAddress[0]);
|
||||
WiFi.softAP(ssid, password);
|
||||
Serial.println("");
|
||||
|
||||
|
||||
@@ -9,8 +9,12 @@ int num_probe = 0;
|
||||
int num_eapol = 0;
|
||||
|
||||
class bluetoothScanAllCallback: public BLEAdvertisedDeviceCallbacks {
|
||||
|
||||
void onResult(BLEAdvertisedDevice advertisedDevice) {
|
||||
|
||||
/* Original BLE */
|
||||
//void onResult(BLEAdvertisedDevice advertisedDevice) {
|
||||
|
||||
/* NimBLE */
|
||||
void onResult(BLEAdvertisedDevice *advertisedDevice) {
|
||||
|
||||
//advertisedDevice.getScan()->stop();
|
||||
|
||||
@@ -18,24 +22,24 @@ class bluetoothScanAllCallback: public BLEAdvertisedDeviceCallbacks {
|
||||
if (display_obj.display_buffer->size() >= 0)
|
||||
{
|
||||
display_string.concat(" RSSI: ");
|
||||
display_string.concat(advertisedDevice.getRSSI());
|
||||
display_string.concat(advertisedDevice->getRSSI());
|
||||
Serial.print(" RSSI: ");
|
||||
Serial.print(advertisedDevice.getRSSI());
|
||||
Serial.print(advertisedDevice->getRSSI());
|
||||
|
||||
display_string.concat(" ");
|
||||
Serial.print(" ");
|
||||
|
||||
Serial.print("Device: ");
|
||||
if(advertisedDevice.getName().length() != 0)
|
||||
if(advertisedDevice->getName().length() != 0)
|
||||
{
|
||||
display_string.concat(advertisedDevice.getName().c_str());
|
||||
Serial.print(advertisedDevice.getName().c_str());
|
||||
display_string.concat(advertisedDevice->getName().c_str());
|
||||
Serial.print(advertisedDevice->getName().c_str());
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
display_string.concat(advertisedDevice.getAddress().toString().c_str());
|
||||
Serial.print(advertisedDevice.getAddress().toString().c_str());
|
||||
display_string.concat(advertisedDevice->getAddress().toString().c_str());
|
||||
Serial.print(advertisedDevice->getAddress().toString().c_str());
|
||||
}
|
||||
|
||||
int temp_len = display_string.length();
|
||||
@@ -56,7 +60,11 @@ class bluetoothScanAllCallback: public BLEAdvertisedDeviceCallbacks {
|
||||
};
|
||||
|
||||
class bluetoothScanSkimmersCallback: public BLEAdvertisedDeviceCallbacks {
|
||||
void onResult(BLEAdvertisedDevice advertisedDevice) {
|
||||
/* Original BLE */
|
||||
//void onResult(BLEAdvertisedDevice advertisedDevice) {
|
||||
|
||||
/* NimBLE */
|
||||
void onResult(BLEAdvertisedDevice *advertisedDevice) {
|
||||
String bad_list[bad_list_length] = {"HC-03", "HC-05", "HC-06"};
|
||||
if (display_obj.display_buffer->size() >= 0)
|
||||
{
|
||||
@@ -65,17 +73,17 @@ class bluetoothScanSkimmersCallback: public BLEAdvertisedDeviceCallbacks {
|
||||
//display_string.concat(" RSSI: ");
|
||||
//display_string.concat(advertisedDevice.getRSSI());
|
||||
//display_string.concat(" ");
|
||||
if(advertisedDevice.getName().length() != 0)
|
||||
if(advertisedDevice->getName().length() != 0)
|
||||
{
|
||||
//display_string.concat(advertisedDevice.getName().c_str());
|
||||
Serial.print(advertisedDevice.getName().c_str());
|
||||
Serial.print(advertisedDevice->getName().c_str());
|
||||
for(int i = 0; i < bad_list_length; i++)
|
||||
{
|
||||
if(strcmp(advertisedDevice.getName().c_str(), bad_list[i].c_str()) == 0)
|
||||
if(strcmp(advertisedDevice->getName().c_str(), bad_list[i].c_str()) == 0)
|
||||
{
|
||||
display_string.concat("Potential Skimmer: ");
|
||||
display_string.concat(" ");
|
||||
display_string.concat(advertisedDevice.getName().c_str());
|
||||
display_string.concat(advertisedDevice->getName().c_str());
|
||||
int temp_len = display_string.length();
|
||||
for (int i = 0; i < 40 - temp_len; i++)
|
||||
{
|
||||
@@ -91,7 +99,7 @@ class bluetoothScanSkimmersCallback: public BLEAdvertisedDeviceCallbacks {
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(advertisedDevice.getAddress().toString().c_str());
|
||||
Serial.print(advertisedDevice->getAddress().toString().c_str());
|
||||
//display_string.concat(advertisedDevice.getAddress().toString().c_str());
|
||||
}
|
||||
/*
|
||||
@@ -102,7 +110,7 @@ class bluetoothScanSkimmersCallback: public BLEAdvertisedDeviceCallbacks {
|
||||
}
|
||||
*/
|
||||
Serial.print(" RSSI: ");
|
||||
Serial.println(advertisedDevice.getRSSI());
|
||||
Serial.println(advertisedDevice->getRSSI());
|
||||
|
||||
/*
|
||||
while (display_obj.printing)
|
||||
@@ -132,6 +140,8 @@ void WiFiScan::StartScan(uint8_t scan_mode, uint16_t color)
|
||||
RunEapolScan(scan_mode, color);
|
||||
else if (scan_mode == WIFI_SCAN_AP)
|
||||
RunBeaconScan(scan_mode, color);
|
||||
else if (scan_mode == WIFI_SCAN_PWN)
|
||||
RunPwnScan(scan_mode, color);
|
||||
else if (scan_mode == WIFI_SCAN_DEAUTH)
|
||||
RunDeauthScan(scan_mode, color);
|
||||
else if (scan_mode == WIFI_PACKET_MONITOR)
|
||||
@@ -144,6 +154,10 @@ void WiFiScan::StartScan(uint8_t scan_mode, uint16_t color)
|
||||
RunBluetoothScan(scan_mode, color);
|
||||
else if (scan_mode == BT_SCAN_SKIMMERS)
|
||||
RunBluetoothScan(scan_mode, color);
|
||||
else if (scan_mode == WIFI_SCAN_ESPRESSIF)
|
||||
RunEspressifScan(scan_mode, color);
|
||||
//else if (scan_mode == LV_JOIN_WIFI)
|
||||
// RunLvJoinWiFi(scan_mode, color);
|
||||
|
||||
WiFiScan::currentScanMode = scan_mode;
|
||||
}
|
||||
@@ -153,6 +167,8 @@ void WiFiScan::StopScan(uint8_t scan_mode)
|
||||
{
|
||||
if ((currentScanMode == WIFI_SCAN_PROBE) ||
|
||||
(currentScanMode == WIFI_SCAN_AP) ||
|
||||
(currentScanMode == WIFI_SCAN_PWN) ||
|
||||
(currentScanMode == WIFI_SCAN_ESPRESSIF) ||
|
||||
(currentScanMode == WIFI_SCAN_EAPOL) ||
|
||||
(currentScanMode == WIFI_SCAN_ALL) ||
|
||||
(currentScanMode == WIFI_SCAN_DEAUTH) ||
|
||||
@@ -248,9 +264,32 @@ String WiFiScan::freeRAM()
|
||||
{
|
||||
char s[150];
|
||||
sprintf(s, "RAM Free: %u bytes", system_get_free_heap_size());
|
||||
this->free_ram = String(system_get_free_heap_size());
|
||||
return String(s);
|
||||
}
|
||||
|
||||
/*
|
||||
void WiFiScan::RunLvJoinWiFi(uint8_t scan_mode, uint16_t color) {
|
||||
|
||||
display_obj.tft.init();
|
||||
display_obj.tft.setRotation(1);
|
||||
|
||||
#ifdef TFT_SHIELD
|
||||
uint16_t calData[5] = { 391, 3491, 266, 3505, 7 }; // Landscape TFT Shield
|
||||
Serial.println("Using TFT Shield");
|
||||
#else if defined(TFT_DIY)
|
||||
uint16_t calData[5] = { 213, 3469, 320, 3446, 1 }; // Landscape TFT DIY
|
||||
Serial.println("Using TFT DIY");
|
||||
#endif
|
||||
display_obj.tft.setTouch(calData);
|
||||
|
||||
display_obj.initLVGL();
|
||||
|
||||
lv_obj_t * scr = lv_cont_create(NULL, NULL);
|
||||
lv_disp_load_scr(scr);
|
||||
|
||||
display_obj.joinWiFiGFX();
|
||||
}*/
|
||||
|
||||
void WiFiScan::RunInfo()
|
||||
{
|
||||
@@ -298,6 +337,34 @@ void WiFiScan::RunInfo()
|
||||
display_obj.tft.println("Internal temp: " + (String)temp_obj.current_temp + " C");
|
||||
}
|
||||
|
||||
void WiFiScan::RunEspressifScan(uint8_t scan_mode, uint16_t color) {
|
||||
sd_obj.openCapture("espressif");
|
||||
|
||||
display_obj.TOP_FIXED_AREA_2 = 48;
|
||||
display_obj.tteBar = true;
|
||||
display_obj.print_delay_1 = 15;
|
||||
display_obj.print_delay_2 = 10;
|
||||
//display_obj.clearScreen();
|
||||
display_obj.initScrollValues(true);
|
||||
display_obj.tft.setTextWrap(false);
|
||||
display_obj.tft.setTextColor(TFT_WHITE, color);
|
||||
display_obj.tft.fillRect(0,16,240,16, color);
|
||||
display_obj.tft.drawCentreString(" Detect Espressif ",120,16,2);
|
||||
display_obj.touchToExit();
|
||||
display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
display_obj.setupScrollArea(display_obj.TOP_FIXED_AREA_2, BOT_FIXED_AREA);
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
esp_wifi_init(&cfg);
|
||||
esp_wifi_set_storage(WIFI_STORAGE_RAM);
|
||||
esp_wifi_set_mode(WIFI_MODE_NULL);
|
||||
esp_wifi_start();
|
||||
esp_wifi_set_promiscuous(true);
|
||||
esp_wifi_set_promiscuous_filter(&filt);
|
||||
esp_wifi_set_promiscuous_rx_cb(&espressifSnifferCallback);
|
||||
esp_wifi_set_channel(set_channel, WIFI_SECOND_CHAN_NONE);
|
||||
initTime = millis();
|
||||
}
|
||||
|
||||
void WiFiScan::RunPacketMonitor(uint8_t scan_mode, uint16_t color)
|
||||
{
|
||||
display_obj.tft.init();
|
||||
@@ -444,6 +511,35 @@ void WiFiScan::RunBeaconSpam(uint8_t scan_mode, uint16_t color)
|
||||
//Serial.println("End of func");
|
||||
}
|
||||
|
||||
void WiFiScan::RunPwnScan(uint8_t scan_mode, uint16_t color)
|
||||
{
|
||||
sd_obj.openCapture("pwnagotchi");
|
||||
|
||||
display_obj.TOP_FIXED_AREA_2 = 48;
|
||||
display_obj.tteBar = true;
|
||||
display_obj.print_delay_1 = 15;
|
||||
display_obj.print_delay_2 = 10;
|
||||
//display_obj.clearScreen();
|
||||
display_obj.initScrollValues(true);
|
||||
display_obj.tft.setTextWrap(false);
|
||||
display_obj.tft.setTextColor(TFT_WHITE, color);
|
||||
display_obj.tft.fillRect(0,16,240,16, color);
|
||||
display_obj.tft.drawCentreString(" Detect Pwnagotchi ",120,16,2);
|
||||
display_obj.touchToExit();
|
||||
display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
display_obj.setupScrollArea(display_obj.TOP_FIXED_AREA_2, BOT_FIXED_AREA);
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
esp_wifi_init(&cfg);
|
||||
esp_wifi_set_storage(WIFI_STORAGE_RAM);
|
||||
esp_wifi_set_mode(WIFI_MODE_NULL);
|
||||
esp_wifi_start();
|
||||
esp_wifi_set_promiscuous(true);
|
||||
esp_wifi_set_promiscuous_filter(&filt);
|
||||
esp_wifi_set_promiscuous_rx_cb(&pwnSnifferCallback);
|
||||
esp_wifi_set_channel(set_channel, WIFI_SECOND_CHAN_NONE);
|
||||
initTime = millis();
|
||||
}
|
||||
|
||||
// Function to start running a beacon scan
|
||||
void WiFiScan::RunBeaconScan(uint8_t scan_mode, uint16_t color)
|
||||
{
|
||||
@@ -613,6 +709,172 @@ void WiFiScan::getMAC(char *addr, uint8_t* data, uint16_t offset) {
|
||||
sprintf(addr, "%02x:%02x:%02x:%02x:%02x:%02x", data[offset+0], data[offset+1], data[offset+2], data[offset+3], data[offset+4], data[offset+5]);
|
||||
}
|
||||
|
||||
void WiFiScan::espressifSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type)
|
||||
{
|
||||
wifi_promiscuous_pkt_t *snifferPacket = (wifi_promiscuous_pkt_t*)buf;
|
||||
WifiMgmtHdr *frameControl = (WifiMgmtHdr*)snifferPacket->payload;
|
||||
wifi_pkt_rx_ctrl_t ctrl = (wifi_pkt_rx_ctrl_t)snifferPacket->rx_ctrl;
|
||||
int len = snifferPacket->rx_ctrl.sig_len;
|
||||
|
||||
String display_string = "";
|
||||
String src_addr_string = "";
|
||||
|
||||
if (type == WIFI_PKT_MGMT)
|
||||
{
|
||||
len -= 4;
|
||||
}
|
||||
int fctl = ntohs(frameControl->fctl);
|
||||
const wifi_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)snifferPacket->payload;
|
||||
const WifiMgmtHdr *hdr = &ipkt->hdr;
|
||||
|
||||
// If we dont the buffer size is not 0, don't write or else we get CORRUPT_HEAP
|
||||
//if ((snifferPacket->payload[0] == 0x80) && (display_obj.display_buffer->size() == 0))
|
||||
//{
|
||||
|
||||
char addr[] = "00:00:00:00:00:00";
|
||||
getMAC(addr, snifferPacket->payload, 10);
|
||||
|
||||
src_addr_string.concat(addr);
|
||||
bool match = false;
|
||||
|
||||
for (int i = 0; i < (sizeof(espressif_macs) / sizeof(espressif_macs[0])); i++) {
|
||||
if (src_addr_string.startsWith(espressif_macs[i])) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!match)
|
||||
return;
|
||||
|
||||
delay(random(0, 10));
|
||||
Serial.print("RSSI: ");
|
||||
Serial.print(snifferPacket->rx_ctrl.rssi);
|
||||
Serial.print(" Ch: ");
|
||||
Serial.print(snifferPacket->rx_ctrl.channel);
|
||||
Serial.print(" BSSID: ");
|
||||
|
||||
Serial.print(addr);
|
||||
//display_string.concat(" RSSI: ");
|
||||
//display_string.concat(snifferPacket->rx_ctrl.rssi);
|
||||
display_string.concat("CH: " + (String)snifferPacket->rx_ctrl.channel);
|
||||
|
||||
//display_string.concat(" ");
|
||||
display_string.concat(" -> ");
|
||||
display_string.concat(addr);
|
||||
|
||||
for (int i = 0; i < 19 - snifferPacket->payload[37]; i++)
|
||||
{
|
||||
display_string.concat(" ");
|
||||
}
|
||||
|
||||
Serial.print(" ");
|
||||
|
||||
//if (display_obj.display_buffer->size() == 0)
|
||||
//{
|
||||
display_obj.loading = true;
|
||||
display_obj.display_buffer->add(display_string);
|
||||
display_obj.loading = false;
|
||||
//}
|
||||
|
||||
|
||||
|
||||
Serial.println();
|
||||
|
||||
sd_obj.addPacket(snifferPacket->payload, len);
|
||||
//}
|
||||
}
|
||||
|
||||
void WiFiScan::pwnSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type)
|
||||
{
|
||||
wifi_promiscuous_pkt_t *snifferPacket = (wifi_promiscuous_pkt_t*)buf;
|
||||
WifiMgmtHdr *frameControl = (WifiMgmtHdr*)snifferPacket->payload;
|
||||
wifi_pkt_rx_ctrl_t ctrl = (wifi_pkt_rx_ctrl_t)snifferPacket->rx_ctrl;
|
||||
int len = snifferPacket->rx_ctrl.sig_len;
|
||||
|
||||
String display_string = "";
|
||||
String src = "";
|
||||
String essid = "";
|
||||
|
||||
if (type == WIFI_PKT_MGMT)
|
||||
{
|
||||
len -= 4;
|
||||
int fctl = ntohs(frameControl->fctl);
|
||||
const wifi_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)snifferPacket->payload;
|
||||
const WifiMgmtHdr *hdr = &ipkt->hdr;
|
||||
|
||||
// If we dont the buffer size is not 0, don't write or else we get CORRUPT_HEAP
|
||||
if ((snifferPacket->payload[0] == 0x80) && (display_obj.display_buffer->size() == 0))
|
||||
{
|
||||
char addr[] = "00:00:00:00:00:00";
|
||||
getMAC(addr, snifferPacket->payload, 10);
|
||||
src.concat(addr);
|
||||
if (src == "de:ad:be:ef:de:ad") {
|
||||
|
||||
|
||||
delay(random(0, 10));
|
||||
Serial.print("RSSI: ");
|
||||
Serial.print(snifferPacket->rx_ctrl.rssi);
|
||||
Serial.print(" Ch: ");
|
||||
Serial.print(snifferPacket->rx_ctrl.channel);
|
||||
Serial.print(" BSSID: ");
|
||||
Serial.print(addr);
|
||||
//display_string.concat(addr);
|
||||
display_string.concat("CH: " + (String)snifferPacket->rx_ctrl.channel);
|
||||
Serial.print(" ESSID: ");
|
||||
display_string.concat(" -> ");
|
||||
|
||||
// Just grab the first 255 bytes of the pwnagotchi beacon
|
||||
// because that is where the name is
|
||||
//for (int i = 0; i < snifferPacket->payload[37]; i++)
|
||||
for (int i = 0; i < len - 37; i++)
|
||||
{
|
||||
Serial.print((char)snifferPacket->payload[i + 38]);
|
||||
//display_string.concat((char)snifferPacket->payload[i + 38]);
|
||||
essid.concat((char)snifferPacket->payload[i + 38]);
|
||||
}
|
||||
//essid.concat("\": \"\"}}");
|
||||
//Serial.println("\n" + (String)(snifferPacket->payload[37]) + " -> " + essid);
|
||||
|
||||
// Load json
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
JsonObject& json = jsonBuffer.parseObject(essid);
|
||||
if (!json.success()) {
|
||||
Serial.println("\nCould not parse Pwnagotchi json");
|
||||
}
|
||||
else {
|
||||
Serial.println("\nSuccessfully parsed json");
|
||||
String json_output;
|
||||
json.printTo(json_output);
|
||||
Serial.println(json_output);
|
||||
display_string.concat(json["name"].as<String>() + " pwnd: " + json["pwnd_tot"].as<String>());
|
||||
}
|
||||
|
||||
int temp_len = display_string.length();
|
||||
for (int i = 0; i < 40 - temp_len; i++)
|
||||
{
|
||||
display_string.concat(" ");
|
||||
}
|
||||
|
||||
Serial.print(" ");
|
||||
|
||||
if (display_obj.display_buffer->size() == 0)
|
||||
{
|
||||
display_obj.loading = true;
|
||||
display_obj.display_buffer->add(display_string);
|
||||
display_obj.loading = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Serial.println();
|
||||
|
||||
sd_obj.addPacket(snifferPacket->payload, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WiFiScan::beaconSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type)
|
||||
{
|
||||
wifi_promiscuous_pkt_t *snifferPacket = (wifi_promiscuous_pkt_t*)buf;
|
||||
@@ -1536,6 +1798,8 @@ void WiFiScan::main(uint32_t currentTime)
|
||||
// WiFi operations
|
||||
if ((currentScanMode == WIFI_SCAN_PROBE) ||
|
||||
(currentScanMode == WIFI_SCAN_AP) ||
|
||||
(currentScanMode == WIFI_SCAN_PWN) ||
|
||||
(currentScanMode == WIFI_SCAN_ESPRESSIF) ||
|
||||
(currentScanMode == WIFI_SCAN_DEAUTH) ||
|
||||
(currentScanMode == WIFI_SCAN_ALL))
|
||||
{
|
||||
@@ -1606,4 +1870,6 @@ void WiFiScan::main(uint32_t currentTime)
|
||||
packets_sent = 0;
|
||||
}
|
||||
}
|
||||
//else if (currentScanMode == LV_JOIN_WIFI)
|
||||
// lv_task_handler();
|
||||
}
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
#ifndef WiFiScan_h
|
||||
#define WiFiScan_h
|
||||
|
||||
#include <BLEDevice.h>
|
||||
#include <BLEUtils.h>
|
||||
#include <BLEScan.h>
|
||||
#include <BLEAdvertisedDevice.h>
|
||||
//#include <BLEDevice.h>
|
||||
//#include <BLEUtils.h>
|
||||
//#include <BLEScan.h>
|
||||
//#include <BLEAdvertisedDevice.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
// Testing NimBLE
|
||||
#include <NimBLEDevice.h>
|
||||
#include <NimBLEAdvertisedDevice.h>
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <math.h>
|
||||
@@ -16,6 +21,7 @@
|
||||
#include "Buffer.h"
|
||||
#include "BatteryInterface.h"
|
||||
#include "TemperatureInterface.h"
|
||||
#include "Assets.h"
|
||||
//#include "MenuFunctions.h"
|
||||
|
||||
#define bad_list_length 3
|
||||
@@ -25,14 +31,17 @@
|
||||
#define WIFI_SCAN_OFF 0
|
||||
#define WIFI_SCAN_PROBE 1
|
||||
#define WIFI_SCAN_AP 2
|
||||
#define WIFI_SCAN_EAPOL 3
|
||||
#define WIFI_SCAN_DEAUTH 4
|
||||
#define WIFI_SCAN_ALL 5
|
||||
#define WIFI_PACKET_MONITOR 6
|
||||
#define WIFI_ATTACK_BEACON_SPAM 7
|
||||
#define WIFI_ATTACK_RICK_ROLL 8
|
||||
#define BT_SCAN_ALL 9
|
||||
#define BT_SCAN_SKIMMERS 10
|
||||
#define WIFI_SCAN_PWN 3
|
||||
#define WIFI_SCAN_EAPOL 4
|
||||
#define WIFI_SCAN_DEAUTH 5
|
||||
#define WIFI_SCAN_ALL 6
|
||||
#define WIFI_PACKET_MONITOR 7
|
||||
#define WIFI_ATTACK_BEACON_SPAM 8
|
||||
#define WIFI_ATTACK_RICK_ROLL 9
|
||||
#define BT_SCAN_ALL 10
|
||||
#define BT_SCAN_SKIMMERS 11
|
||||
#define WIFI_SCAN_ESPRESSIF 12
|
||||
//#define LV_JOIN_WIFI 12
|
||||
|
||||
#define GRAPH_REFRESH 100
|
||||
|
||||
@@ -68,12 +77,12 @@ class WiFiScan
|
||||
|
||||
uint32_t initTime = 0;
|
||||
bool run_setup = true;
|
||||
int set_channel = 1;
|
||||
int bluetoothScanTime = 5;
|
||||
int packets_sent = 0;
|
||||
const wifi_promiscuous_filter_t filt = {.filter_mask=WIFI_PROMIS_FILTER_MASK_MGMT | WIFI_PROMIS_FILTER_MASK_DATA};
|
||||
BLEScan* pBLEScan;
|
||||
|
||||
String connected_network = "";
|
||||
String alfa = "1234567890qwertyuiopasdfghjkklzxcvbnm QWERTYUIOPASDFGHJKLZXCVBNM_";
|
||||
|
||||
char* rick_roll[8] = {
|
||||
@@ -131,19 +140,29 @@ class WiFiScan
|
||||
void broadcastSetSSID(uint32_t current_time, char* ESSID);
|
||||
void RunRickRoll(uint8_t scan_mode, uint16_t color);
|
||||
void RunBeaconSpam(uint8_t scan_mode, uint16_t color);
|
||||
void RunEspressifScan(uint8_t scan_mode, uint16_t color);
|
||||
void RunPwnScan(uint8_t scan_mode, uint16_t color);
|
||||
void RunBeaconScan(uint8_t scan_mode, uint16_t color);
|
||||
void RunDeauthScan(uint8_t scan_mode, uint16_t color);
|
||||
void RunEapolScan(uint8_t scan_mode, uint16_t color);
|
||||
void RunProbeScan(uint8_t scan_mode, uint16_t color);
|
||||
void RunPacketMonitor(uint8_t scan_mode, uint16_t color);
|
||||
void RunBluetoothScan(uint8_t scan_mode, uint16_t color);
|
||||
//void RunLvJoinWiFi(uint8_t scan_mode, uint16_t color);
|
||||
static void scanCompleteCB(BLEScanResults scanResults);
|
||||
|
||||
public:
|
||||
WiFiScan();
|
||||
|
||||
int set_channel = 1;
|
||||
|
||||
int old_channel = 0;
|
||||
|
||||
bool orient_display = false;
|
||||
|
||||
String free_ram = "";
|
||||
String old_free_ram = "";
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
|
||||
String getStaMAC();
|
||||
@@ -157,6 +176,8 @@ class WiFiScan
|
||||
void StopScan(uint8_t scan_mode);
|
||||
|
||||
static void getMAC(char *addr, uint8_t* data, uint16_t offset);
|
||||
static void espressifSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type);
|
||||
static void pwnSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type);
|
||||
static void beaconSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type);
|
||||
static void deauthSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type);
|
||||
static void probeSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type);
|
||||
|
||||
BIN
esp32_marauder/data/marauder3L1.jpg
Normal file
|
After Width: | Height: | Size: 24 KiB |
@@ -55,11 +55,14 @@ uint32_t currentTime = 0;
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
pinMode(FLASH_BUTTON, INPUT);
|
||||
pinMode(TFT_BL, OUTPUT);
|
||||
digitalWrite(TFT_BL, LOW);
|
||||
|
||||
#if BATTERY_ANALOG_ON == 1
|
||||
pinMode(BATTERY_PIN, OUTPUT);
|
||||
pinMode(CHARGING_PIN, INPUT);
|
||||
#endif
|
||||
|
||||
// Preset SPI CS pins to avoid bus conflicts
|
||||
digitalWrite(TFT_CS, HIGH);
|
||||
digitalWrite(SD_CS, HIGH);
|
||||
@@ -67,6 +70,15 @@ void setup()
|
||||
Serial.begin(115200);
|
||||
|
||||
Serial.begin(115200);
|
||||
|
||||
display_obj.RunSetup();
|
||||
display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
|
||||
digitalWrite(TFT_BL, HIGH);
|
||||
|
||||
display_obj.tft.println("Marauder " + display_obj.version_number + "\n");
|
||||
|
||||
display_obj.tft.println("Started Serial");
|
||||
|
||||
Serial.println("\n\n--------------------------------\n");
|
||||
Serial.println(" ESP32 Marauder \n");
|
||||
Serial.println(" " + display_obj.version_number + "\n");
|
||||
@@ -75,27 +87,44 @@ void setup()
|
||||
|
||||
//Serial.println("Internal Temp: " + (String)((temprature_sens_read() - 32) / 1.8));
|
||||
|
||||
// Do some LED stuff
|
||||
led_obj.RunSetup();
|
||||
Serial.println(wifi_scan_obj.freeRAM());
|
||||
|
||||
display_obj.tft.println("Checked RAM");
|
||||
|
||||
// Do some SD stuff
|
||||
if(sd_obj.initSD())
|
||||
if(sd_obj.initSD()) {
|
||||
Serial.println("SD Card supported");
|
||||
else
|
||||
display_obj.tft.println("Initialized SD Card");
|
||||
}
|
||||
else {
|
||||
Serial.println("SD Card NOT Supported");
|
||||
display_obj.tft.setTextColor(TFT_RED, TFT_BLACK);
|
||||
display_obj.tft.println("Failed to Initialize SD Card");
|
||||
display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK);
|
||||
}
|
||||
|
||||
// Run display setup
|
||||
display_obj.RunSetup();
|
||||
Serial.println(wifi_scan_obj.freeRAM());
|
||||
//display_obj.RunSetup();
|
||||
|
||||
// Build menus
|
||||
menu_function_obj.RunSetup();
|
||||
Serial.println(wifi_scan_obj.freeRAM());
|
||||
//menu_function_obj.RunSetup();
|
||||
|
||||
//display_obj.tft.println("Created Menu Structure");
|
||||
|
||||
// Battery stuff
|
||||
Serial.println(wifi_scan_obj.freeRAM());
|
||||
battery_obj.RunSetup();
|
||||
|
||||
display_obj.tft.println("Checked battery configuration");
|
||||
|
||||
// Temperature stuff
|
||||
Serial.println(wifi_scan_obj.freeRAM());
|
||||
temp_obj.RunSetup();
|
||||
|
||||
display_obj.tft.println("Initialized temperature interface");
|
||||
|
||||
battery_obj.battery_level = battery_obj.getBatteryLevel();
|
||||
|
||||
if (battery_obj.i2c_supported) {
|
||||
@@ -105,6 +134,31 @@ void setup()
|
||||
Serial.println("IP5306 I2C Supported: false");
|
||||
|
||||
Serial.println(wifi_scan_obj.freeRAM());
|
||||
|
||||
// Do some LED stuff
|
||||
led_obj.RunSetup();
|
||||
|
||||
display_obj.tft.println("Initialized LED Interface");
|
||||
|
||||
display_obj.tft.println("Starting...");
|
||||
|
||||
delay(1000);
|
||||
|
||||
display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
|
||||
digitalWrite(TFT_BL, LOW);
|
||||
|
||||
// Draw the title screen
|
||||
display_obj.drawJpeg("/marauder3L.jpg", 0 , 0); // 240 x 320 image
|
||||
|
||||
//showCenterText(version_number, 250);
|
||||
display_obj.tft.drawCentreString(display_obj.version_number, 120, 250, 2);
|
||||
|
||||
digitalWrite(TFT_BL, HIGH);
|
||||
|
||||
delay(5000);
|
||||
|
||||
menu_function_obj.RunSetup();
|
||||
}
|
||||
|
||||
|
||||
|
||||
BIN
esp32_marauder/esp32_marauder_v0_7_0_20200719_6.bin
Normal file
BIN
esp32_marauder/esp32_marauder_v0_7_0_20200819_1.bin
Normal file
BIN
pictures/IMG_0420.JPG
Normal file
|
After Width: | Height: | Size: 7.4 MiB |
BIN
pictures/IMG_0421.JPG
Normal file
|
After Width: | Height: | Size: 7.3 MiB |
BIN
pictures/IMG_0423.JPG
Normal file
|
After Width: | Height: | Size: 7.5 MiB |
BIN
pictures/IMG_0424.JPG
Normal file
|
After Width: | Height: | Size: 8.3 MiB |
BIN
pictures/IMG_0425.JPG
Normal file
|
After Width: | Height: | Size: 6.6 MiB |
BIN
pictures/IMG_0426.JPG
Normal file
|
After Width: | Height: | Size: 7.0 MiB |
BIN
pictures/IMG_2519 - Copy.jpg
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
pictures/IMG_2520 - Copy.jpg
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
pictures/diy.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
pictures/icons/espressif_22.bmp
Normal file
|
After Width: | Height: | Size: 382 B |
BIN
pictures/icons/pwnagotchi_22.bmp
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
pictures/m5stack.jpg
Normal file
|
After Width: | Height: | Size: 67 KiB |
BIN
pictures/odroid_marauder.jpg
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
9
pictures/xbm/espressif_22.XBM
Normal file
@@ -0,0 +1,9 @@
|
||||
#define 1593729689573_width 22
|
||||
#define 1593729689573_height 22
|
||||
static char 1593729689573_bits[] = {
|
||||
0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0x3F, 0xFF, 0xC7, 0x3F, 0x7F, 0x0E, 0x3F,
|
||||
0x2F, 0x30, 0x3E, 0x37, 0x40, 0x3C, 0xF3, 0x83, 0x38, 0x0B, 0x04, 0x39,
|
||||
0x03, 0x18, 0x32, 0x01, 0x20, 0x32, 0xF1, 0x21, 0x34, 0x01, 0x46, 0x34,
|
||||
0x03, 0x84, 0x38, 0x7B, 0x88, 0x38, 0x93, 0x88, 0x38, 0x17, 0x89, 0x3C,
|
||||
0x07, 0x89, 0x3F, 0xCF, 0x89, 0x3D, 0x9F, 0x49, 0x3C, 0x7F, 0x00, 0x3F,
|
||||
0xFF, 0xE3, 0x3F, 0xFF, 0xFF, 0x3F, };
|
||||
9
pictures/xbm/pwnagotchi_22.XBM
Normal file
@@ -0,0 +1,9 @@
|
||||
#define 1592872258566_width 22
|
||||
#define 1592872258566_height 22
|
||||
static char 1592872258566_bits[] = {
|
||||
0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0x3F, 0x7F, 0x80, 0x3F, 0xBF, 0x7F, 0x3F,
|
||||
0xDF, 0xC0, 0x3E, 0x6F, 0xBF, 0x3D, 0xBF, 0x61, 0x3F, 0xFF, 0xDE, 0x3F,
|
||||
0xFF, 0xF3, 0x3F, 0xFF, 0xFF, 0x3F, 0xFB, 0xFF, 0x37, 0xFD, 0xFF, 0x2F,
|
||||
0xFE, 0xFF, 0x1F, 0x8E, 0x7F, 0x1C, 0x36, 0xBF, 0x19, 0x16, 0xBF, 0x18,
|
||||
0x06, 0x3F, 0x18, 0x8E, 0x7F, 0x1C, 0xFD, 0xFF, 0x2F, 0xDB, 0xF3, 0x36,
|
||||
0x3F, 0x0C, 0x3F, 0xFF, 0xFF, 0x3F, };
|
||||