diff --git a/esp32_marauder/CommandLine.cpp b/esp32_marauder/CommandLine.cpp index 9c3b9d7..b43238e 100644 --- a/esp32_marauder/CommandLine.cpp +++ b/esp32_marauder/CommandLine.cpp @@ -308,11 +308,11 @@ void CommandLine::runCommand(String input) { wifi_scan_obj.StartScan(WIFI_SCAN_OFF); if(old_scan_mode == WIFI_SCAN_GPS_NMEA) - Serial.println("END OF NMEA STREAM"); + Serial.println(F("END OF NMEA STREAM")); else if(old_scan_mode == WIFI_SCAN_GPS_DATA) - Serial.println("Stopping GPS data updates"); + Serial.println(F("Stopping GPS data updates")); else - Serial.println("Stopping WiFi tran/recv"); + Serial.println(F("Stopping WiFi tran/recv")); // If we don't do this, the text and button coordinates will be off #ifdef HAS_SCREEN @@ -375,7 +375,7 @@ void CommandLine::runCommand(String input) { Serial.println(gps_obj.getNmeaNotparsed()); } else - Serial.println("You did not provide a valid argument"); + Serial.println(F("You did not provide a valid argument")); } else if(nmea_arg != -1){ String nmea_type = cmd_args.get(nmea_arg + 1); @@ -391,7 +391,7 @@ void CommandLine::runCommand(String input) { Serial.println("GPS Output Type Set To: " + nmea_type); } else - Serial.println("You did not provide a valid argument"); + Serial.println(F("You did not provide a valid argument")); } else if (track_arg != -1) { wifi_scan_obj.currentScanMode = GPS_TRACKER; @@ -401,9 +401,9 @@ void CommandLine::runCommand(String input) { wifi_scan_obj.StartScan(GPS_TRACKER, TFT_CYAN); } else if(cmd_args.size()>1) - Serial.println("You did not provide a valid flag"); + Serial.println(F("You did not provide a valid flag")); else - Serial.println("You did not provide an argument"); + Serial.println(F("You did not provide an argument")); } #endif } @@ -413,7 +413,7 @@ void CommandLine::runCommand(String input) { #ifdef HAS_SCREEN menu_function_obj.changeMenu(&menu_function_obj.gpsInfoMenu); #endif - Serial.println("NMEA STREAM FOLLOWS"); + Serial.println(F("NMEA STREAM FOLLOWS")); wifi_scan_obj.currentScanMode = WIFI_SCAN_GPS_NMEA; wifi_scan_obj.StartScan(WIFI_SCAN_GPS_NMEA, TFT_CYAN); } @@ -444,7 +444,7 @@ void CommandLine::runCommand(String input) { } } #else - Serial.println("This hardware does not support neopixel"); + Serial.println(F("This hardware does not support neopixel")); #endif } // ls command @@ -453,9 +453,9 @@ void CommandLine::runCommand(String input) { if (cmd_args.size() > 1) sd_obj.listDir(cmd_args.get(1)); else - Serial.println("You did not provide a dir to list"); + Serial.println(F("You did not provide a dir to list")); #else - Serial.println("SD support disabled, cannot use command"); + Serial.println(F("SD support disabled, cannot use command")); return; #endif } @@ -524,7 +524,7 @@ void CommandLine::runCommand(String input) { else if (da_sw != -1) result = settings_obj.saveSetting(setting_name, false); else { - Serial.println("You did not properly enable/disable this setting."); + Serial.println(F("You did not properly enable/disable this setting.")); return; } @@ -536,7 +536,7 @@ void CommandLine::runCommand(String input) { } else if (cmd_args.get(0) == REBOOT_CMD) { - Serial.println("Rebooting..."); + Serial.println(F("Rebooting...")); ESP.restart(); } @@ -569,8 +569,25 @@ void CommandLine::runCommand(String input) { #ifdef HAS_GPS if (gps_obj.getGpsModuleStatus()) { int sta_sw = this->argSearch(&cmd_args, "-s"); + int flk_sw = this->argSearch(&cmd_args, "-f"); - if (sta_sw == -1) { + if (flk_sw == -1) { + Serial.println("Starting Flock Wardrive. Stop with " + (String)STOPSCAN_CMD); + #ifdef HAS_SCREEN + display_obj.clearScreen(); + menu_function_obj.drawStatusBar(); + #endif + wifi_scan_obj.StartScan(BT_SCAN_FLOCK_WARDRIVE, TFT_GREEN); + } + else if (sta_sw != -1) { + Serial.println("Starting Station Wardrive. Stop with " + (String)STOPSCAN_CMD); + #ifdef HAS_SCREEN + display_obj.clearScreen(); + menu_function_obj.drawStatusBar(); + #endif + wifi_scan_obj.StartScan(WIFI_SCAN_STATION_WAR_DRIVE, TFT_GREEN); + } + else { Serial.println("Starting Wardrive. Stop with " + (String)STOPSCAN_CMD); #ifdef HAS_SCREEN display_obj.clearScreen(); @@ -578,18 +595,11 @@ void CommandLine::runCommand(String input) { #endif wifi_scan_obj.StartScan(WIFI_SCAN_WAR_DRIVE, TFT_GREEN); } - else {Serial.println("Starting Station Wardrive. Stop with " + (String)STOPSCAN_CMD); - #ifdef HAS_SCREEN - display_obj.clearScreen(); - menu_function_obj.drawStatusBar(); - #endif - wifi_scan_obj.StartScan(WIFI_SCAN_STATION_WAR_DRIVE, TFT_GREEN); - } } else - Serial.println("GPS Module not detected"); + Serial.println(F("GPS Module not detected")); #else - Serial.println("GPS not supported"); + Serial.println(F("GPS not supported")); #endif } // Karma @@ -597,14 +607,14 @@ void CommandLine::runCommand(String input) { int pr_sw = this->argSearch(&cmd_args, "-p"); if (pr_sw == -1) { - Serial.println("You did not provide a target index"); + Serial.println(F("You did not provide a target index")); return; } int pr_index = cmd_args.get(pr_sw + 1).toInt(); if ((pr_index < 0) || (pr_index > probe_req_ssids->size() - 1)) { - Serial.println("The provided index was not in range"); + Serial.println(F("The provided index was not in range")); return; } @@ -618,7 +628,7 @@ void CommandLine::runCommand(String input) { wifi_scan_obj.setMac(); } else { - Serial.println("Unable to set AP ESSID"); + Serial.println(F("Unable to set AP ESSID")); return; } @@ -839,14 +849,14 @@ void CommandLine::runCommand(String input) { int ap_sw = this->argSearch(&cmd_args, "-a"); // APs if (ap_sw == -1) { - Serial.println("You did not provide a target index"); + Serial.println(F("You did not provide a target index")); return; } int ap_index = cmd_args.get(ap_sw + 1).toInt(); if ((ap_index < 0) || (ap_index > access_points->size() - 1)) { - Serial.println("The provided index was not in range"); + Serial.println(F("The provided index was not in range")); return; } @@ -865,14 +875,14 @@ void CommandLine::runCommand(String input) { int cl_sw = this->argSearch(&cmd_args, "-s"); // Stations if (cl_sw == -1) { - Serial.println("You did not provide a target index"); + Serial.println(F("You did not provide a target index")); return; } int sta_index = cmd_args.get(cl_sw + 1).toInt(); if ((sta_index < 0) || (sta_index > stations->size() - 1)) { - Serial.println("The provided index was not in range"); + Serial.println(F("The provided index was not in range")); return; } @@ -900,7 +910,7 @@ void CommandLine::runCommand(String input) { int targ_sw = this->argSearch(&cmd_args, "-c"); if (attack_type_switch == -1) { - Serial.println("You must specify an attack type"); + Serial.println(F("You must specify an attack type")); return; } else { @@ -911,7 +921,7 @@ void CommandLine::runCommand(String input) { if (attack_type == ATTACK_TYPE_DEAUTH) { // Default to broadcast if ((dst_addr_sw == -1) && (targ_sw == -1)) { - Serial.println("Sending to broadcast..."); + Serial.println(F("Sending to broadcast...")); wifi_scan_obj.dst_mac = "ff:ff:ff:ff:ff:ff"; } // Dest addr specified @@ -921,7 +931,7 @@ void CommandLine::runCommand(String input) { } // Station list specified else if (targ_sw != -1) - Serial.println("Sending to Station list"); + Serial.println(F("Sending to Station list")); // Source addr not specified if (src_addr_sw == -1) { @@ -1066,7 +1076,7 @@ void CommandLine::runCommand(String input) { wifi_scan_obj.StartScan(WIFI_ATTACK_FUNNY_BEACON, TFT_CYAN); } else { - Serial.println("Attack type not properly defined"); + Serial.println(F("Attack type not properly defined")); return; } } @@ -1120,7 +1130,7 @@ void CommandLine::runCommand(String input) { wifi_scan_obj.StartScan(BT_SCAN_ALL, TFT_GREEN); } #else - Serial.println("Bluetooth not supported"); + Serial.println(F("Bluetooth not supported")); #endif } else if (cmd_args.get(0) == BT_SPOOFAT_CMD) { @@ -1165,7 +1175,7 @@ void CommandLine::runCommand(String input) { #endif wifi_scan_obj.StartScan(BT_ATTACK_SOUR_APPLE, TFT_GREEN); #else - Serial.println("Bluetooth not supported"); + Serial.println(F("Bluetooth not supported")); #endif } else if (bt_type == "windows") { @@ -1177,7 +1187,7 @@ void CommandLine::runCommand(String input) { #endif wifi_scan_obj.StartScan(BT_ATTACK_SWIFTPAIR_SPAM, TFT_CYAN); #else - Serial.println("Bluetooth not supported"); + Serial.println(F("Bluetooth not supported")); #endif } else if (bt_type == "samsung") { @@ -1189,7 +1199,7 @@ void CommandLine::runCommand(String input) { #endif wifi_scan_obj.StartScan(BT_ATTACK_SAMSUNG_SPAM, TFT_CYAN); #else - Serial.println("Bluetooth not supported"); + Serial.println(F("Bluetooth not supported")); #endif } else if (bt_type == "google") { @@ -1201,7 +1211,7 @@ void CommandLine::runCommand(String input) { #endif wifi_scan_obj.StartScan(BT_ATTACK_GOOGLE_SPAM, TFT_CYAN); #else - Serial.println("Bluetooth not supported"); + Serial.println(F("Bluetooth not supported")); #endif } else if (bt_type == "flipper") { @@ -1213,7 +1223,7 @@ void CommandLine::runCommand(String input) { #endif wifi_scan_obj.StartScan(BT_ATTACK_FLIPPER_SPAM, TFT_ORANGE); #else - Serial.println("Bluetooth not supported"); + Serial.println(F("Bluetooth not supported")); #endif } else if (bt_type == "all") { @@ -1225,11 +1235,11 @@ void CommandLine::runCommand(String input) { #endif wifi_scan_obj.StartScan(BT_ATTACK_SPAM_ALL, TFT_MAGENTA); #else - Serial.println("Bluetooth not supported"); + Serial.println(F("Bluetooth not supported")); #endif } else { - Serial.println("You did not specify a correct spam type"); + Serial.println(F("You did not specify a correct spam type")); } } } @@ -1257,12 +1267,12 @@ void CommandLine::runCommand(String input) { } } else - Serial.println("GPS Module not detected"); + Serial.println(F("GPS Module not detected")); #else - Serial.println("GPS not supported"); + Serial.println(F("GPS not supported")); #endif #else - Serial.println("Bluetooth not supported"); + Serial.println(F("Bluetooth not supported")); #endif } @@ -1276,7 +1286,7 @@ void CommandLine::runCommand(String input) { #endif wifi_scan_obj.StartScan(BT_SCAN_SKIMMERS, TFT_MAGENTA); #else - Serial.println("Bluetooth not supported"); + Serial.println(F("Bluetooth not supported")); #endif } @@ -1298,13 +1308,13 @@ void CommandLine::runCommand(String input) { if (sd_sw != -1) { #ifdef HAS_SD if (!sd_obj.supported) { - Serial.println("SD card is not connected. Cannot perform SD Update"); + Serial.println(F("SD card is not connected. Cannot perform SD Update")); return; } wifi_scan_obj.currentScanMode = OTA_UPDATE; sd_obj.runUpdate(); #else - Serial.println("SD card support disabled. Cannot perform SD Update"); + Serial.println(F("SD card support disabled. Cannot perform SD Update")); return; #endif } @@ -1323,12 +1333,14 @@ void CommandLine::runCommand(String input) { } if (cmd_args.get(0) == ARP_SCAN_CMD) { - Serial.println("Starting ARP Scan. Stop with " + (String)STOPSCAN_CMD); - #ifdef HAS_SCREEN - display_obj.clearScreen(); - menu_function_obj.drawStatusBar(); + #ifndef HAS_DUAL_BAND + Serial.println("Starting ARP Scan. Stop with " + (String)STOPSCAN_CMD); + #ifdef HAS_SCREEN + display_obj.clearScreen(); + menu_function_obj.drawStatusBar(); + #endif + wifi_scan_obj.StartScan(WIFI_ARP_SCAN, TFT_CYAN); #endif - wifi_scan_obj.StartScan(WIFI_ARP_SCAN, TFT_CYAN); } // GPS POI @@ -1376,7 +1388,7 @@ void CommandLine::runCommand(String input) { #endif } #else - Serial.println("Your hardware doesn't have GPS, silly"); + Serial.println(F("Your hardware doesn't have GPS, silly")); return; #endif } @@ -1406,7 +1418,7 @@ void CommandLine::runCommand(String input) { } } else { - Serial.println("The IP index specified is out of range"); + Serial.println(F("The IP index specified is out of range")); return; } } @@ -1438,12 +1450,12 @@ void CommandLine::runCommand(String input) { wifi_scan_obj.StartScan(target_mode, TFT_CYAN); } else { - Serial.println("You did not specify a supported service"); + Serial.println(F("You did not specify a supported service")); return; } } else { - Serial.println("You did not specify an IP index"); + Serial.println(F("You did not specify an IP index")); return; } } @@ -1525,7 +1537,7 @@ void CommandLine::runCommand(String input) { } } else { - Serial.println("You did not specify which list to show"); + Serial.println(F("You did not specify which list to show")); return; } } @@ -1573,11 +1585,11 @@ void CommandLine::runCommand(String input) { #endif } else { - Serial.println("There are no saved WiFi credentials"); + Serial.println(F("There are no saved WiFi credentials")); } } else { - Serial.println("You did not provide the proper args"); + Serial.println(F("You did not provide the proper args")); return; } } @@ -1747,7 +1759,7 @@ void CommandLine::runCommand(String input) { this->showCounts(count_selected, count_unselected); } else { - Serial.println("You did not specify which list to select from"); + Serial.println(F("You did not specify which list to select from")); return; } } @@ -1806,7 +1818,7 @@ void CommandLine::runCommand(String input) { wifi_scan_obj.addSSID(essid); } else { - Serial.println("You did not specify how to add SSIDs"); + Serial.println(F("You did not specify how to add SSIDs")); } } // Remove SSID @@ -1819,7 +1831,7 @@ void CommandLine::runCommand(String input) { ssids->remove(index); } else { - Serial.println("You did not specify whether to add or remove SSIDs"); + Serial.println(F("You did not specify whether to add or remove SSIDs")); return; } } diff --git a/esp32_marauder/CommandLine.h b/esp32_marauder/CommandLine.h index 8800e9d..22f956b 100644 --- a/esp32_marauder/CommandLine.h +++ b/esp32_marauder/CommandLine.h @@ -148,7 +148,7 @@ const char PROGMEM HELP_SNIFF_ESP_CMD[] = "sniffesp"; const char PROGMEM HELP_SNIFF_DEAUTH_CMD[] = "sniffdeauth"; const char PROGMEM HELP_SNIFF_PMKID_CMD[] = "sniffpmkid [-c ][-d][-l]"; const char PROGMEM HELP_STOPSCAN_CMD[] = "stopscan [-f]"; -const char PROGMEM HELP_WARDRIVE_CMD[] = "wardrive [-s]"; +const char PROGMEM HELP_WARDRIVE_CMD[] = "wardrive [-s/-f]"; const char PROGMEM HELP_PING_CMD[] = "pingscan"; const char PROGMEM HELP_PORT_SCAN_CMD[] = "portscan [-a -t ]/[-s ]"; const char PROGMEM HELP_ARP_SCAN_CMD[] = "arpscan [-f]"; diff --git a/esp32_marauder/Display.cpp b/esp32_marauder/Display.cpp index e8356fd..76bb08e 100644 --- a/esp32_marauder/Display.cpp +++ b/esp32_marauder/Display.cpp @@ -1045,9 +1045,9 @@ void Display::buildBanner(String msg, int xpos) void Display::main(uint8_t scan_mode) { - if ((scan_mode == LV_JOIN_WIFI) || + /*if ((scan_mode == LV_JOIN_WIFI) || (scan_mode == LV_ADD_SSID)) - lv_task_handler(); + lv_task_handler();*/ return; } // End SPIFFS_functions diff --git a/esp32_marauder/Display.h b/esp32_marauder/Display.h index a570b0e..5f03705 100644 --- a/esp32_marauder/Display.h +++ b/esp32_marauder/Display.h @@ -12,7 +12,7 @@ //#include #include #include -#include +//#include #include #include "SPIFFS.h" #include "Assets.h" diff --git a/esp32_marauder/EvilPortal.cpp b/esp32_marauder/EvilPortal.cpp index b651ff5..d6d348d 100644 --- a/esp32_marauder/EvilPortal.cpp +++ b/esp32_marauder/EvilPortal.cpp @@ -61,9 +61,9 @@ void EvilPortal::setupServer() { #ifndef HAS_PSRAM server.on("/", HTTP_GET, [this](AsyncWebServerRequest *request) { request->send_P(200, "text/html", index_html); - Serial.println("client connected"); + Serial.println(F("client connected")); #ifdef HAS_SCREEN - this->sendToDisplay("Client connected to server"); + this->sendToDisplay(F("Client connected to server")); #endif }); #else @@ -71,7 +71,7 @@ void EvilPortal::setupServer() { request->send(200, "text/html", index_html); Serial.println("client connected"); #ifdef HAS_SCREEN - this->sendToDisplay("Client connected to server"); + this->sendToDisplay(F("Client connected to server")); #endif }); #endif @@ -144,10 +144,10 @@ void EvilPortal::setHtmlFromSerial() { bool EvilPortal::setHtml() { if (this->using_serial_html) { - Serial.println("html previously set"); + Serial.println(F("html previously set")); return true; } - Serial.println("Setting HTML..."); + Serial.println(F("Setting HTML...")); #ifdef HAS_SD File html_file = sd_obj.getFile("/" + this->target_html_name); #else @@ -156,7 +156,7 @@ bool EvilPortal::setHtml() { if (!html_file) { #ifdef HAS_SCREEN this->sendToDisplay("Could not find /" + this->target_html_name); - this->sendToDisplay("Touch to exit..."); + this->sendToDisplay(F("Touch to exit...")); #endif Serial.println("Could not find /" + this->target_html_name + ". Use stopscan..."); return false; @@ -164,9 +164,9 @@ bool EvilPortal::setHtml() { else { if (html_file.size() > MAX_HTML_SIZE) { #ifdef HAS_SCREEN - this->sendToDisplay("The given HTML is too large."); + this->sendToDisplay(F("The given HTML is too large.")); this->sendToDisplay("The Byte limit is " + (String)MAX_HTML_SIZE); - this->sendToDisplay("Touch to exit..."); + this->sendToDisplay(F("Touch to exit...")); #endif Serial.println("The provided HTML is too large. Byte limit is " + (String)MAX_HTML_SIZE + "\nUse stopscan..."); return false; @@ -316,14 +316,14 @@ bool EvilPortal::setAP(String essid) { strncpy(apName, essid.c_str(), MAX_AP_NAME_SIZE); this->has_ap = true; - Serial.println("ap config set"); + Serial.println(F("ap config set")); return true; } void EvilPortal::startAP() { const IPAddress AP_IP(172, 0, 0, 1); - Serial.print("starting ap "); + Serial.print(F("starting ap ")); Serial.println(apName); WiFi.mode(WIFI_AP); @@ -334,19 +334,19 @@ void EvilPortal::startAP() { this->sendToDisplay("AP started"); #endif - Serial.print("ap ip address: "); + Serial.print(F("ap ip address: ")); Serial.println(WiFi.softAPIP()); this->setupServer(); - Serial.println("Server endpoints configured"); + Serial.println(F("Server endpoints configured")); this->dnsServer.start(53, "*", WiFi.softAPIP()); - Serial.println("DNS Server started"); + Serial.println(F("DNS Server started")); server.addHandler(new CaptiveRequestHandler()).setFilter(ON_AP_FILTER); - Serial.println("Captive Portal handler started"); + Serial.println(F("Captive Portal handler started")); server.begin(); - Serial.println("Server started"); + Serial.println(F("Server started")); #ifdef HAS_SCREEN this->sendToDisplay("Evil Portal READY"); #endif @@ -375,20 +375,29 @@ void EvilPortal::sendToDisplay(String msg) { } void EvilPortal::main(uint8_t scan_mode) { - if ((scan_mode == WIFI_SCAN_EVIL_PORTAL) && (this->has_ap) && (this->has_html)){ - this->dnsServer.processNextRequest(); - if (this->name_received && this->password_received) { - this->name_received = false; - this->password_received = false; - String logValue1 = - "u: " + this->user_name; - String logValue2 = "p: " + this->password; - String full_string = logValue1 + " " + logValue2 + "\n"; - Serial.print(full_string); - buffer_obj.append(full_string); - #ifdef HAS_SCREEN - this->sendToDisplay(full_string); - #endif - } + if (scan_mode != WIFI_SCAN_EVIL_PORTAL || !this->has_ap || !this->has_html) { + return; + } + + this->dnsServer.processNextRequest(); + + if (this->name_received && this->password_received) { + this->name_received = false; + this->password_received = false; + + // Adjust size depending on your max username/password length + char line[96]; + + // If user_name / password are still Arduino String: + snprintf(line, sizeof(line), + "u: %s p: %s\n", + this->user_name.c_str(), + this->password.c_str()); + + Serial.print(line); + buffer_obj.append(line); + #ifdef HAS_SCREEN + this->sendToDisplay(line); + #endif } } diff --git a/esp32_marauder/MenuFunctions.cpp b/esp32_marauder/MenuFunctions.cpp index fc1be9d..5257f8f 100644 --- a/esp32_marauder/MenuFunctions.cpp +++ b/esp32_marauder/MenuFunctions.cpp @@ -1,689 +1,14 @@ #include "MenuFunctions.h" #include "lang_var.h" -//#include "icons.h" #ifdef HAS_SCREEN extern const unsigned char menu_icons[][66]; -PROGMEM lv_obj_t * slider_label; -PROGMEM lv_obj_t * ta1; -PROGMEM lv_obj_t * ta2; -PROGMEM lv_obj_t * save_name; MenuFunctions::MenuFunctions() { } -// LVGL Stuff -/* Interrupt driven periodic handler */ - -#ifdef HAS_ILI9341 - void MenuFunctions::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.updateTouch(&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; - - data->point.x = touchX; - data->point.y = touchY; - - } - - return false; - } - - void MenuFunctions::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 MenuFunctions::deinitLVGL() { - Serial.println(F("Deinit LVGL")); - //lv_deinit(); - } - - - // Event handler for settings drop down menus - void setting_dropdown_cb(lv_obj_t * obj, lv_event_t event) { - - } - - // GFX Function to build a list showing all Stations scanned - void MenuFunctions::addStationGFX(){ - extern LinkedList* stations; - extern LinkedList* access_points; - extern WiFiScan wifi_scan_obj; - - lv_obj_t * list1 = lv_list_create(lv_scr_act(), NULL); - lv_obj_set_size(list1, 160, 200); - lv_obj_set_width(list1, LV_HOR_RES); - lv_obj_align(list1, NULL, LV_ALIGN_CENTER, 0, 0); - - lv_obj_t * list_btn; - - lv_obj_t * label; - - list_btn = lv_list_add_btn(list1, LV_SYMBOL_CLOSE, text09); - lv_obj_set_event_cb(list_btn, station_list_cb); - - char addr[] = "00:00:00:00:00:00"; - for (int x = 0; x < access_points->size(); x++) { - AccessPoint cur_ap = access_points->get(x); - - // Add non clickable button for AP - String full_label = "AP: " + cur_ap.essid; - char buf[full_label.length() + 1] = {}; - full_label.toCharArray(buf, full_label.length() + 1); - list_btn = lv_list_add_btn(list1, NULL, buf); - lv_btn_set_checkable(list_btn, false); - - int cur_ap_sta_len = access_points->get(x).stations->size(); - for (int y = 0; y < cur_ap_sta_len; y++) { - Station cur_sta = stations->get(cur_ap.stations->get(y)); - // Convert uint8_t MAC to char array - wifi_scan_obj.getMAC(addr, cur_sta.mac, 0); - - list_btn = lv_list_add_btn(list1, LV_SYMBOL_WIFI, addr); - lv_btn_set_checkable(list_btn, true); - lv_obj_set_event_cb(list_btn, station_list_cb); - - if (cur_sta.selected) - lv_btn_toggle(list_btn); - } - } - } - - // Function to work with list of Stations - void station_list_cb(lv_obj_t * btn, lv_event_t event) { - extern LinkedList* stations; - extern MenuFunctions menu_function_obj; - extern WiFiScan wifi_scan_obj; - - String btn_text = lv_list_get_btn_text(btn); - String display_string = ""; - char addr[] = "00:00:00:00:00:00"; - - if (event == LV_EVENT_CLICKED) { - if (btn_text != text09) { - } - else { - Serial.println("Exiting..."); - lv_obj_del_async(lv_obj_get_parent(lv_obj_get_parent(btn))); - - for (int i = 0; i < stations->size(); i++) { - if (stations->get(i).selected) { - wifi_scan_obj.getMAC(addr, stations->get(i).mac, 0); - Serial.print("Selected: "); - Serial.println(addr); - } - } - - printf("LV_EVENT_CANCEL\n"); - menu_function_obj.deinitLVGL(); - wifi_scan_obj.StartScan(WIFI_SCAN_OFF); - display_obj.exit_draw = true; // set everything back to normal - } - } - - if (event == LV_EVENT_VALUE_CHANGED) { - if (lv_btn_get_state(btn) == LV_BTN_STATE_CHECKED_RELEASED) { - for (int i = 0; i < stations->size(); i++) { - wifi_scan_obj.getMAC(addr, stations->get(i).mac, 0); - if (strcmp(addr, btn_text.c_str()) == 0) { - Serial.print("Adding Station: "); - Serial.println(addr); - Station sta = stations->get(i); - sta.selected = true; - stations->set(i, sta); - } - } - } - else { - for (int i = 0; i < stations->size(); i++) { - wifi_scan_obj.getMAC(addr, stations->get(i).mac, 0); - if (strcmp(addr, btn_text.c_str()) == 0) { - Serial.print("Removing Station: "); - Serial.println(addr); - Station sta = stations->get(i); - sta.selected = false; - stations->set(i, sta); - } - } - } - } - } - - // GFX Function to build a list showing all EP HTML Files - void MenuFunctions::selectEPHTMLGFX() { - extern EvilPortal evil_portal_obj; - - lv_obj_t * list1 = lv_list_create(lv_scr_act(), NULL); - lv_obj_set_size(list1, 160, 200); - lv_obj_set_width(list1, LV_HOR_RES); - lv_obj_align(list1, NULL, LV_ALIGN_CENTER, 0, 0); - - lv_obj_t * list_btn; - - lv_obj_t * label; - - list_btn = lv_list_add_btn(list1, LV_SYMBOL_CLOSE, text09); - lv_obj_set_event_cb(list_btn, html_list_cb); - - for (int i = 1; i < evil_portal_obj.html_files->size(); i++) { - char buf[evil_portal_obj.html_files->get(i).length() + 1] = {}; - evil_portal_obj.html_files->get(i).toCharArray(buf, evil_portal_obj.html_files->get(i).length() + 1); - - list_btn = lv_list_add_btn(list1, LV_SYMBOL_FILE, buf); - lv_btn_set_checkable(list_btn, true); - lv_obj_set_event_cb(list_btn, html_list_cb); - - if (i == evil_portal_obj.selected_html_index) - lv_btn_toggle(list_btn); - } - } - - void html_list_cb(lv_obj_t * btn, lv_event_t event) { - extern EvilPortal evil_portal_obj; - extern MenuFunctions menu_function_obj; - - String btn_text = lv_list_get_btn_text(btn); - String display_string = ""; - - if (event == LV_EVENT_CLICKED) { - if (btn_text != text09) { - } - else { - Serial.println("Exiting..."); - lv_obj_del_async(lv_obj_get_parent(lv_obj_get_parent(btn))); - - for (int i = 1; i < evil_portal_obj.html_files->size(); i++) { - if (i == evil_portal_obj.selected_html_index) { - Serial.println("Selected: " + (String)evil_portal_obj.html_files->get(i)); - } - } - - printf("LV_EVENT_CANCEL\n"); - menu_function_obj.deinitLVGL(); - wifi_scan_obj.StartScan(WIFI_SCAN_OFF); - display_obj.exit_draw = true; // set everything back to normal - } - } - - if (event == LV_EVENT_VALUE_CHANGED) { - if (lv_btn_get_state(btn) == LV_BTN_STATE_CHECKED_RELEASED) { - for (int i = 1; i < evil_portal_obj.html_files->size(); i++) { - if (evil_portal_obj.html_files->get(i) == btn_text) { - Serial.println("Setting HTML: " + (String)evil_portal_obj.html_files->get(i)); - evil_portal_obj.selected_html_index = i; - evil_portal_obj.target_html_name = (String)evil_portal_obj.html_files->get(i); - } - } - - // Deselect buttons that were previously selected - lv_obj_t * list = lv_obj_get_parent(btn); - - lv_obj_t * next_btn = lv_obj_get_child(list, NULL); - while (next_btn != NULL) { - if (next_btn != btn) { - lv_btn_set_state(next_btn, LV_BTN_STATE_RELEASED); - } - next_btn = lv_obj_get_child(list, next_btn); - } - } - } - } - - // GFX Function to build a list showing all APs scanned - void MenuFunctions::addAPGFX(String type){ - extern WiFiScan wifi_scan_obj; - extern LinkedList* access_points; - extern LinkedList* airtags; - - lv_obj_t * list1 = lv_list_create(lv_scr_act(), NULL); - lv_obj_set_size(list1, 160, 200); - lv_obj_set_width(list1, LV_HOR_RES); - lv_obj_align(list1, NULL, LV_ALIGN_CENTER, 0, 0); - - lv_obj_t * list_btn; - - lv_obj_t * label; - - list_btn = lv_list_add_btn(list1, LV_SYMBOL_CLOSE, text09); - lv_obj_set_event_cb(list_btn, ap_list_cb); - - if ((type == "AP") || (type == "AP Info")) { - for (int i = 0; i < access_points->size(); i++) { - char buf[access_points->get(i).essid.length() + 1] = {}; - access_points->get(i).essid.toCharArray(buf, access_points->get(i).essid.length() + 1); - - list_btn = lv_list_add_btn(list1, LV_SYMBOL_WIFI, buf); - lv_btn_set_checkable(list_btn, true); - if (type == "AP") - lv_obj_set_event_cb(list_btn, ap_list_cb); - else if (type == "AP Info") - lv_obj_set_event_cb(list_btn, ap_info_list_cb); - - if (access_points->get(i).selected) - lv_btn_toggle(list_btn); - } - } - else if (type == "Airtag") { - for (int i = 0; i < airtags->size(); i++) { - char buf[airtags->get(i).mac.length() + 1] = {}; - airtags->get(i).mac.toCharArray(buf, airtags->get(i).mac.length() + 1); - - list_btn = lv_list_add_btn(list1, LV_SYMBOL_BLUETOOTH, buf); - lv_btn_set_checkable(list_btn, true); - lv_obj_set_event_cb(list_btn, at_list_cb); - - //if (airtags->get(i).selected) - // lv_btn_toggle(list_btn); - } - } - } - - void at_list_cb(lv_obj_t * btn, lv_event_t event) { - extern MenuFunctions menu_function_obj; - extern WiFiScan wifi_scan_obj; - extern LinkedList* airtags; - extern Display display_obj; - - String btn_text = lv_list_get_btn_text(btn); - String display_string = ""; - - // Button is clicked - if (event == LV_EVENT_CLICKED) { - if (btn_text != text09) { - } - // It's the back button - else { - Serial.println("Exiting..."); - lv_obj_del_async(lv_obj_get_parent(lv_obj_get_parent(btn))); - - for (int i = 0; i < airtags->size(); i++) { - if (airtags->get(i).selected) { - Serial.println("Selected: " + (String)airtags->get(i).mac); - } - } - - printf("LV_EVENT_CANCEL\n"); - menu_function_obj.deinitLVGL(); - wifi_scan_obj.StartScan(WIFI_SCAN_OFF); - display_obj.exit_draw = true; // set everything back to normal - } - } - - if (event == LV_EVENT_VALUE_CHANGED) { - if (lv_btn_get_state(btn) == LV_BTN_STATE_CHECKED_RELEASED) { - bool do_that_thang = false; - for (int i = 0; i < airtags->size(); i++) { - if (airtags->get(i).mac == btn_text) { - Serial.println("Selecting Airtag: " + (String)airtags->get(i).mac); - AirTag at = airtags->get(i); - at.selected = true; - airtags->set(i, at); - do_that_thang = true; - } - else { - AirTag at = airtags->get(i); - at.selected = false; - airtags->set(i, at); - } - } - // Start spoofing airtag - if (do_that_thang) { - menu_function_obj.deinitLVGL(); - lv_obj_del_async(lv_obj_get_parent(lv_obj_get_parent(btn))); - wifi_scan_obj.StartScan(WIFI_SCAN_OFF); - display_obj.clearScreen(); - menu_function_obj.orientDisplay(); - display_obj.clearScreen(); - menu_function_obj.drawStatusBar(); - wifi_scan_obj.StartScan(BT_SPOOF_AIRTAG, TFT_WHITE); - } - } - else { - for (int i = 0; i < airtags->size(); i++) { - if (airtags->get(i).mac == btn_text) { - Serial.println("Deselecting Airtag: " + (String)airtags->get(i).mac); - AirTag at = airtags->get(i); - at.selected = false; - airtags->set(i, at); - } - } - } - } - } - - void ap_list_cb(lv_obj_t * btn, lv_event_t event) { - extern LinkedList* access_points; - extern MenuFunctions menu_function_obj; - extern WiFiScan wifi_scan_obj; - - String btn_text = lv_list_get_btn_text(btn); - String display_string = ""; - - if (event == LV_EVENT_CLICKED) { - if (btn_text != text09) { - } - else { - Serial.println("Exiting..."); - lv_obj_del_async(lv_obj_get_parent(lv_obj_get_parent(btn))); - - for (int i = 0; i < access_points->size(); i++) { - if (access_points->get(i).selected) { - Serial.println("Selected: " + (String)access_points->get(i).essid); - } - } - - printf("LV_EVENT_CANCEL\n"); - menu_function_obj.deinitLVGL(); - wifi_scan_obj.StartScan(WIFI_SCAN_OFF); - display_obj.exit_draw = true; // set everything back to normal - } - } - - if (event == LV_EVENT_VALUE_CHANGED) { - if (lv_btn_get_state(btn) == LV_BTN_STATE_CHECKED_RELEASED) { - for (int i = 0; i < access_points->size(); i++) { - if (access_points->get(i).essid == btn_text) { - Serial.println("Adding AP: " + (String)access_points->get(i).essid); - AccessPoint ap = access_points->get(i); - ap.selected = true; - access_points->set(i, ap); - } - } - } - else { - for (int i = 0; i < access_points->size(); i++) { - if (access_points->get(i).essid == btn_text) { - Serial.println("Removing AP: " + (String)access_points->get(i).essid); - AccessPoint ap = access_points->get(i); - ap.selected = false; - access_points->set(i, ap); - } - } - } - } - } - - void ap_info_list_cb(lv_obj_t * btn, lv_event_t event) { - extern LinkedList* access_points; - extern MenuFunctions menu_function_obj; - extern WiFiScan wifi_scan_obj; - - String btn_text = lv_list_get_btn_text(btn); - String display_string = ""; - - // Exit function - if (event == LV_EVENT_CLICKED) { - if (btn_text != text09) { - for (int i = 0; i < access_points->size(); i++) { - if (access_points->get(i).essid == btn_text) { - lv_obj_del_async(lv_obj_get_parent(lv_obj_get_parent(btn))); - - printf("LV_EVENT_CANCEL\n"); - menu_function_obj.deinitLVGL(); - wifi_scan_obj.StartScan(WIFI_SCAN_OFF); - //display_obj.exit_draw = true; // set everything back to normal - menu_function_obj.orientDisplay(); - menu_function_obj.changeMenu(&menu_function_obj.apInfoMenu); - wifi_scan_obj.RunAPInfo(i); - } - } - } - else { - Serial.println("Exiting..."); - lv_obj_del_async(lv_obj_get_parent(lv_obj_get_parent(btn))); - - printf("LV_EVENT_CANCEL\n"); - menu_function_obj.deinitLVGL(); - wifi_scan_obj.StartScan(WIFI_SCAN_OFF); - display_obj.exit_draw = true; // set everything back to normal - } - } - } - - void MenuFunctions::addSSIDGFX(){ - extern LinkedList* ssids; - - String display_string = ""; - // 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, add_ssid_keyboard_event_cb); - - // Create one text area - // Store all SSIDs - ta1 = lv_textarea_create(lv_scr_act(), NULL); - lv_textarea_set_one_line(ta1, false); - lv_obj_set_width(ta1, LV_HOR_RES); - lv_obj_set_height(ta1, (LV_VER_RES / 2) - 35); - lv_obj_set_pos(ta1, 5, 20); - lv_textarea_set_cursor_hidden(ta1, true); - lv_obj_align(ta1, NULL, LV_ALIGN_IN_TOP_MID, NULL, NULL); - lv_textarea_set_placeholder_text(ta1, text_table1[0]); - - // Create second text area - // Add SSIDs - ta2 = lv_textarea_create(lv_scr_act(), ta1); - lv_textarea_set_cursor_hidden(ta2, false); - lv_textarea_set_one_line(ta2, true); - lv_obj_align(ta2, NULL, LV_ALIGN_IN_TOP_MID, NULL, (LV_VER_RES / 2) - 35); - lv_textarea_set_text(ta2, ""); - lv_textarea_set_placeholder_text(ta2, text_table1[1]); - - // After generating text areas, add text to first text box - for (int i = 0; i < ssids->size(); i++) - display_string.concat((String)ssids->get(i).essid + "\n"); - - lv_textarea_set_text(ta1, display_string.c_str()); - - // Focus it on one of the text areas to start - lv_keyboard_set_textarea(kb, ta2); - lv_keyboard_set_cursor_manage(kb, true); - - } - - // Keyboard callback dedicated to joining wifi - void add_ssid_keyboard_event_cb(lv_obj_t * keyboard, lv_event_t event){ - extern Display display_obj; - extern MenuFunctions menu_function_obj; - extern WiFiScan wifi_scan_obj; - extern LinkedList* ssids; - - lv_keyboard_def_event_cb(kb, event); - - // User has applied text box - if(event == LV_EVENT_APPLY){ - String display_string = ""; - printf("LV_EVENT_APPLY\n"); - - // Get text from SSID text box - String ta2_text = lv_textarea_get_text(ta2); - Serial.println(ta2_text); - - // Add text box text to list of SSIDs - wifi_scan_obj.addSSID(ta2_text); - - // Update large text box with ssid - for (int i = 0; i < ssids->size(); i++) - display_string.concat((String)ssids->get(i).essid + "\n"); - lv_textarea_set_text(ta1, display_string.c_str()); - - lv_textarea_set_text(ta2, ""); - }else if(event == LV_EVENT_CANCEL){ - printf("LV_EVENT_CANCEL\n"); - menu_function_obj.deinitLVGL(); - display_obj.exit_draw = true; // set everything back to normal - } - } - - void MenuFunctions::joinWiFiGFX(String essid, bool start_ap){ - - // 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_textarea_set_text(ta1, essid.c_str()); - 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_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_textarea_set_text(ta2, ""); - 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); - - if (!start_ap) - lv_obj_set_event_cb(kb, join_wifi_keyboard_event_cb); - else - lv_obj_set_event_cb(kb, start_ap_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 join_wifi_keyboard_event_cb(lv_obj_t * keyboard, lv_event_t event){ - extern Display display_obj; - extern MenuFunctions menu_function_obj; - extern WiFiScan wifi_scan_obj; - lv_keyboard_def_event_cb(kb, event); - if(event == LV_EVENT_APPLY){ - printf("LV_EVENT_APPLY\n"); - String ta1_text = lv_textarea_get_text(ta1); - String ta2_text = lv_textarea_get_text(ta2); - Serial.println(ta1_text); - Serial.println(ta2_text); - if (wifi_scan_obj.joinWiFi(ta1_text, ta2_text)) - wifi_scan_obj.currentScanMode = WIFI_CONNECTED; - else - wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF; - }else if(event == LV_EVENT_CANCEL){ - printf("LV_EVENT_CANCEL\n"); - menu_function_obj.deinitLVGL(); - display_obj.exit_draw = true; // set everything back to normal - if (wifi_scan_obj.connected_network != "") - wifi_scan_obj.currentScanMode = WIFI_CONNECTED; - } - } - - void start_ap_keyboard_event_cb(lv_obj_t * keyboard, lv_event_t event){ - extern Display display_obj; - extern MenuFunctions menu_function_obj; - extern WiFiScan wifi_scan_obj; - lv_keyboard_def_event_cb(kb, event); - if(event == LV_EVENT_APPLY){ - printf("LV_EVENT_APPLY\n"); - String ta1_text = lv_textarea_get_text(ta1); - String ta2_text = lv_textarea_get_text(ta2); - Serial.println(ta1_text); - Serial.println(ta2_text); - if (wifi_scan_obj.startWiFi(ta1_text, ta2_text)) - wifi_scan_obj.currentScanMode = WIFI_CONNECTED; - else - wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF; - }else if(event == LV_EVENT_CANCEL){ - printf("LV_EVENT_CANCEL\n"); - menu_function_obj.deinitLVGL(); - display_obj.exit_draw = true; // set everything back to normal - if (wifi_scan_obj.connected_network != "") - wifi_scan_obj.currentScanMode = WIFI_CONNECTED; - } - } - - - 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); - } - - } - -#endif -//// END LV_ARDUINO STUFF - void MenuFunctions::buttonNotSelected(int b, int x) { if (x == -1) x = b; @@ -2005,10 +1330,6 @@ void MenuFunctions::RunSetup() extern LinkedList* ssids; this->disable_touch = false; - - #ifdef HAS_ILI9341 - this->initLVGL(); - #endif #ifdef MARAUDER_CARDPUTER M5CardputerKeyboard.begin(); @@ -2030,14 +1351,11 @@ void MenuFunctions::RunSetup() // Device menu stuff failedUpdateMenu.list = new LinkedList(); - //whichUpdateMenu.list = new LinkedList(); confirmMenu.list = new LinkedList(); updateMenu.list = new LinkedList(); settingsMenu.list = new LinkedList(); specSettingMenu.list = new LinkedList(); infoMenu.list = new LinkedList(); - languageMenu.list = new LinkedList(); - // WiFi menu stuff wifiSnifferMenu.list = new LinkedList(); wifiScannerMenu.list = new LinkedList(); @@ -2051,26 +1369,15 @@ void MenuFunctions::RunSetup() apInfoMenu.list = new LinkedList(); setMacMenu.list = new LinkedList(); genAPMacMenu.list = new LinkedList(); - #ifdef HAS_BT - airtagMenu.list = new LinkedList(); - #endif - //#ifndef HAS_ILI9341 - wifiStationMenu.list = new LinkedList(); - //#endif + wifiStationMenu.list = new LinkedList(); selectProbeSSIDsMenu.list = new LinkedList(); // WiFi HTML menu stuff htmlMenu.list = new LinkedList(); - //#if (!defined(HAS_ILI9341) && defined(HAS_BUTTONS)) - miniKbMenu.list = new LinkedList(); - //#endif - //#ifndef HAS_ILI9341 - // #ifdef HAS_BUTTONS - #ifdef HAS_SD - sdDeleteMenu.list = new LinkedList(); - #endif - // #endif - //#endif + miniKbMenu.list = new LinkedList(); + #ifdef HAS_SD + sdDeleteMenu.list = new LinkedList(); + #endif // Bluetooth menu stuff bluetoothSnifferMenu.list = new LinkedList(); @@ -2099,10 +1406,8 @@ void MenuFunctions::RunSetup() wifiMenu.name = text_table1[7]; deviceMenu.name = text_table1[9]; failedUpdateMenu.name = text_table1[11]; - //whichUpdateMenu.name = text_table1[12]; confirmMenu.name = text_table1[13]; updateMenu.name = text_table1[15]; - languageMenu.name = text_table1[16]; infoMenu.name = text_table1[17]; settingsMenu.name = text_table1[18]; bluetoothMenu.name = text_table1[19]; @@ -2123,30 +1428,21 @@ void MenuFunctions::RunSetup() generateSSIDsMenu.name = text_table1[27]; clearSSIDsMenu.name = text_table1[28]; clearAPsMenu.name = text_table1[29]; - wifiAPMenu.name = "Access Points"; + wifiAPMenu.name = "Select"; wifiIPMenu.name = "Active IPs"; apInfoMenu.name = "AP Info"; setMacMenu.name = "Set MACs"; genAPMacMenu.name = "Generate AP MAC"; - #ifdef HAS_BT - airtagMenu.name = "Select Airtag"; - #endif - //#ifndef HAS_ILI9341 - wifiStationMenu.name = "Select Stations"; - //#endif + wifiStationMenu.name = "Select Stations"; #ifdef HAS_GPS gpsMenu.name = "GPS"; gpsInfoMenu.name = "GPS Data"; wardrivingMenu.name = "Wardriving"; #endif htmlMenu.name = "EP HTML List"; - //#if (!defined(HAS_ILI9341) && defined(HAS_BUTTONS)) - miniKbMenu.name = "Mini Keyboard"; - //#endif + miniKbMenu.name = "Mini Keyboard"; #ifdef HAS_SD - // #ifndef HAS_ILI9341 - sdDeleteMenu.name = "Delete SD Files"; - // #endif + sdDeleteMenu.name = "Delete SD Files"; #endif selectProbeSSIDsMenu.name = "Probe Requests"; evilPortalMenu.name = "Evil Portal"; @@ -2209,11 +1505,13 @@ void MenuFunctions::RunSetup() this->drawStatusBar(); wifi_scan_obj.StartScan(WIFI_PING_SCAN, TFT_CYAN); }); - this->addNodes(&wifiScannerMenu, "ARP Scan", TFTCYAN, NULL, SCANNERS, [this]() { - display_obj.clearScreen(); - this->drawStatusBar(); - wifi_scan_obj.StartScan(WIFI_ARP_SCAN, TFT_CYAN); - }); + #ifndef HAS_DUAL_BAND + this->addNodes(&wifiScannerMenu, "ARP Scan", TFTCYAN, NULL, SCANNERS, [this]() { + display_obj.clearScreen(); + this->drawStatusBar(); + wifi_scan_obj.StartScan(WIFI_ARP_SCAN, TFT_CYAN); + }); + #endif this->addNodes(&wifiScannerMenu, "Port Scan All", TFTMAGENTA, NULL, BEACON_LIST, [this](){ // Add the back button wifiIPMenu.list->clear(); @@ -2314,12 +1612,6 @@ void MenuFunctions::RunSetup() this->drawStatusBar(); wifi_scan_obj.StartScan(WIFI_PACKET_MONITOR, TFT_BLUE); }); - /*this->addNodes(&wifiSnifferMenu, "Packet Count", TFTORANGE, NULL, PACKET_MONITOR, [this]() { - display_obj.clearScreen(); - this->drawStatusBar(); - wifi_scan_obj.StartScan(WIFI_SCAN_PACKET_RATE, TFT_ORANGE); - wifi_scan_obj.renderPacketRate(); - });*/ #endif this->addNodes(&wifiSnifferMenu, "Channel Analyzer", TFTCYAN, NULL, PACKET_MONITOR, [this]() { display_obj.clearScreen(); @@ -2357,32 +1649,26 @@ void MenuFunctions::RunSetup() this->drawStatusBar(); wifi_scan_obj.StartScan(WIFI_SCAN_MULTISSID, TFT_ORANGE); }); - //#ifndef HAS_ILI9341 - this->addNodes(&wifiSnifferMenu, text_table1[49], TFTMAGENTA, NULL, BEACON_SNIFF, [this]() { - display_obj.clearScreen(); - this->drawStatusBar(); - wifi_scan_obj.StartScan(WIFI_SCAN_TARGET_AP, TFT_MAGENTA); - }); - //#endif - this->addNodes(&wifiSnifferMenu, "Scan All", TFTLIME, NULL, BEACON_SNIFF, [this]() { + this->addNodes(&wifiSnifferMenu, text_table1[49], TFTMAGENTA, NULL, BEACON_SNIFF, [this]() { + display_obj.clearScreen(); + this->drawStatusBar(); + wifi_scan_obj.StartScan(WIFI_SCAN_TARGET_AP, TFT_MAGENTA); + }); + this->addNodes(&wifiSnifferMenu, "Scan AP/STA", TFTLIME, NULL, BEACON_SNIFF, [this]() { display_obj.clearScreen(); this->drawStatusBar(); wifi_scan_obj.StartScan(WIFI_SCAN_AP_STA, 0x97e0); }); - //#ifndef HAS_ILI9341 - this->addNodes(&wifiSnifferMenu, text_table1[59], TFTORANGE, NULL, PACKET_MONITOR, [this]() { - display_obj.clearScreen(); - this->drawStatusBar(); - wifi_scan_obj.StartScan(WIFI_SCAN_STATION, TFT_WHITE); - }); - //#endif - //#ifdef HAS_ILI9341 + this->addNodes(&wifiSnifferMenu, text_table1[59], TFTORANGE, NULL, PACKET_MONITOR, [this]() { + display_obj.clearScreen(); + this->drawStatusBar(); + wifi_scan_obj.StartScan(WIFI_SCAN_STATION, TFT_WHITE); + }); this->addNodes(&wifiSnifferMenu, "Signal Monitor", TFTCYAN, NULL, PACKET_MONITOR, [this]() { display_obj.clearScreen(); this->drawStatusBar(); wifi_scan_obj.StartScan(WIFI_SCAN_SIG_STREN, TFT_CYAN); }); - //#endif // Build Wardriving menu #ifdef HAS_GPS @@ -2438,12 +1724,6 @@ void MenuFunctions::RunSetup() this->drawStatusBar(); wifi_scan_obj.StartScan(WIFI_ATTACK_AUTH, TFT_RED); }); - /*this->addNodes(&wifiAttackMenu, "Evil Portal", TFTORANGE, NULL, BEACON_SNIFF, [this]() { - display_obj.clearScreen(); - this->drawStatusBar(); - wifi_scan_obj.StartScan(WIFI_SCAN_EVIL_PORTAL, TFT_ORANGE); - wifi_scan_obj.setMac(); - });*/ this->addNodes(&wifiAttackMenu, "Evil Portal", TFTORANGE, NULL, BEACON_SNIFF, [this]() { wifiAPMenu.list->clear(); @@ -2641,15 +1921,29 @@ void MenuFunctions::RunSetup() #ifdef HAS_ILI9341 this->addNodes(&wifiGeneralMenu, text_table1[1], TFTNAVY, NULL, KEYBOARD_ICO, [this](){ - display_obj.clearScreen(); - wifi_scan_obj.StartScan(LV_ADD_SSID, TFT_YELLOW); - addSSIDGFX(); + 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, NULL, KEYBOARD_ICO, [this](){ this->changeMenu(&miniKbMenu, true); - this->miniKeyboard(&miniKbMenu); + #ifdef HAS_MINI_KB + this->miniKeyboard(&miniKbMenu); + #endif }); #endif this->addNodes(&wifiGeneralMenu, text_table1[28], TFTSILVER, NULL, CLEAR_ICO, [this]() { @@ -2871,9 +2165,12 @@ void MenuFunctions::RunSetup() // Join WiFi using touch screen keyboard #ifdef HAS_TOUCH - wifi_scan_obj.currentScanMode = LV_JOIN_WIFI; - wifi_scan_obj.StartScan(LV_JOIN_WIFI, TFT_YELLOW); - joinWiFiGFX(access_points->get(i).essid); + 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, false); #endif }); } @@ -2914,9 +2211,12 @@ void MenuFunctions::RunSetup() // Join WiFi using touch screen keyboard #ifdef HAS_TOUCH - wifi_scan_obj.currentScanMode = LV_JOIN_WIFI; - wifi_scan_obj.StartScan(LV_JOIN_WIFI, TFT_YELLOW); - joinWiFiGFX(access_points->get(i).essid); + 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, false); #endif }); } @@ -2952,73 +2252,23 @@ void MenuFunctions::RunSetup() // Join WiFi using touch screen keyboard #ifdef HAS_TOUCH - wifi_scan_obj.currentScanMode = LV_JOIN_WIFI; - wifi_scan_obj.StartScan(LV_JOIN_WIFI, TFT_YELLOW); - joinWiFiGFX(ssids->get(i).essid, true); + 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, "Start Saved AP", TFTWHITE, NULL, KEYBOARD_ICO, [this](){ - String ssid = settings_obj.loadSetting("APSSID"); - String pw = settings_obj.loadSetting("APPW"); - - if ((ssid != "") && (pw != "")) { - wifi_scan_obj.startWiFi(ssid, pw, false); - this->changeMenu(&wifiGeneralMenu); - } - else { - // Add the back button - wifiAPMenu.list->clear(); - this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, NULL, 0, [this]() { - this->changeMenu(wifiAPMenu.parentMenu); - }); - - // Populate the menu with buttons - for (int i = 0; i < ssids->size(); i++) { - // This is the menu node - this->addNodes(&wifiAPMenu, ssids->get(i).essid, TFTCYAN, NULL, 255, [this, i](){ - // Join WiFi using mini keyboard - #ifdef HAS_MINI_KB - this->changeMenu(&miniKbMenu); - 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); - } - #endif - - // Join WiFi using touch screen keyboard - #ifdef HAS_TOUCH - wifi_scan_obj.currentScanMode = LV_JOIN_WIFI; - wifi_scan_obj.StartScan(LV_JOIN_WIFI, TFT_YELLOW); - joinWiFiGFX(ssids->get(i).essid, true); - #endif - }); - } - this->changeMenu(&wifiAPMenu); - } - });*/ - wifiStationMenu.parentMenu = &ssidsMenu; this->addNodes(&wifiStationMenu, text09, TFTLIGHTGREY, NULL, 0, [this]() { this->changeMenu(wifiStationMenu.parentMenu, true); }); - //#endif - - //#ifdef HAS_ILI9341 - // this->addNodes(&wifiGeneralMenu, "View AP Info", TFTLIGHTGREY, NULL, 0, [this]() { - // display_obj.clearScreen(); - // wifi_scan_obj.currentScanMode = LV_ADD_SSID; - // wifi_scan_obj.StartScan(LV_ADD_SSID, TFT_WHITE); - // addAPGFX("AP Info"); - // }); - //#endif this->addNodes(&wifiGeneralMenu, "Set MACs", TFTLIGHTGREY, NULL, 0, [this]() { this->changeMenu(&setMacMenu, true); @@ -3183,16 +2433,6 @@ void MenuFunctions::RunSetup() this->drawStatusBar(); wifi_scan_obj.StartScan(BT_SCAN_FLOCK_WARDRIVE, TFT_CYAN); }); - /*this->addNodes(&bluetoothSnifferMenu, "Simple Sniff", TFTWHITE, NULL, BLUETOOTH_SNIFF, [this]() { - display_obj.clearScreen(); - this->drawStatusBar(); - wifi_scan_obj.StartScan(BT_SCAN_SIMPLE, TFT_ORANGE); - }); - this->addNodes(&bluetoothSnifferMenu, "Simple Sniff 2", TFTWHITE, NULL, BLUETOOTH_SNIFF, [this]() { - display_obj.clearScreen(); - this->drawStatusBar(); - wifi_scan_obj.StartScan(BT_SCAN_SIMPLE_TWO, TFT_ORANGE); - });*/ // Bluetooth Attack menu bluetoothAttackMenu.parentMenu = &bluetoothMenu; // Second Menu is third menu parent @@ -3230,23 +2470,14 @@ void MenuFunctions::RunSetup() wifi_scan_obj.StartScan(BT_ATTACK_SPAM_ALL, TFT_MAGENTA); }); - #ifdef HAS_ILI9341 - this->addNodes(&bluetoothAttackMenu, "Spoof Airtag", TFTWHITE, NULL, ATTACKS, [this](){ - display_obj.clearScreen(); - wifi_scan_obj.currentScanMode = LV_ADD_SSID; - wifi_scan_obj.StartScan(LV_ADD_SSID, TFT_WHITE); - addAPGFX("Airtag"); - }); - #endif - - #ifndef HAS_ILI9341 + //#ifndef HAS_ILI9341 #ifdef HAS_BT // Select Airtag on Mini this->addNodes(&bluetoothAttackMenu, "Spoof Airtag", TFTWHITE, NULL, ATTACKS, [this](){ // Clear nodes and add back button - airtagMenu.list->clear(); - this->addNodes(&airtagMenu, text09, TFT_LIGHTGREY, NULL, 0, [this]() { - this->changeMenu(airtagMenu.parentMenu, true); + wifiAPMenu.list->clear(); + this->addNodes(&wifiAPMenu, text09, TFT_LIGHTGREY, NULL, 0, [this]() { + this->changeMenu(wifiAPMenu.parentMenu, true); }); // Add buttons for all airtags @@ -3259,7 +2490,7 @@ void MenuFunctions::RunSetup() // Create the menu nodes for all of the list items for (int i = 0; i < menu_limit; i++) { - this->addNodes(&airtagMenu, airtags->get(i).mac, TFTWHITE, NULL, BLUETOOTH, [this, i](){ + this->addNodes(&wifiAPMenu, airtags->get(i).mac, TFTWHITE, NULL, BLUETOOTH, [this, i](){ AirTag new_at = airtags->get(i); new_at.selected = true; @@ -3281,26 +2512,22 @@ void MenuFunctions::RunSetup() }); } - this->changeMenu(&airtagMenu, true); + this->changeMenu(&wifiAPMenu, true); }); - airtagMenu.parentMenu = &bluetoothAttackMenu; - this->addNodes(&airtagMenu, text09, TFTLIGHTGREY, NULL, 0, [this]() { - this->changeMenu(airtagMenu.parentMenu, true); + wifiAPMenu.parentMenu = &bluetoothAttackMenu; + this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, NULL, 0, [this]() { + this->changeMenu(wifiAPMenu.parentMenu, true); }); #endif - #endif + //#endif // Device menu deviceMenu.parentMenu = &mainMenu; this->addNodes(&deviceMenu, text09, TFTLIGHTGREY, NULL, 0, [this]() { this->changeMenu(deviceMenu.parentMenu, true); }); - /*this->addNodes(&deviceMenu, text_table1[15], TFTORANGE, NULL, UPDATE, [this]() { - wifi_scan_obj.currentScanMode = OTA_UPDATE; - this->changeMenu(&whichUpdateMenu, true); - });*/ #ifdef HAS_SD if (sd_obj.supported) { @@ -3320,35 +2547,12 @@ void MenuFunctions::RunSetup() this->changeMenu(&sdDeleteMenu, true); }); } - - /*if (sd_obj.supported) { - addNodes(&whichUpdateMenu, text_table1[40], TFTMAGENTA, NULL, SD_UPDATE, [this]() { - wifi_scan_obj.currentScanMode = OTA_UPDATE; - this->changeMenu(&confirmMenu, true); - }); - } - - // Confirm SD update menu - confirmMenu.parentMenu = &whichUpdateMenu; - this->addNodes(&confirmMenu, text09, TFTLIGHTGREY, NULL, 0, [this]() { - this->changeMenu(confirmMenu.parentMenu, true); - }); - this->addNodes(&confirmMenu, text14, TFTORANGE, NULL, UPDATE, [this]() { - wifi_scan_obj.currentScanMode = OTA_UPDATE; - this->changeMenu(&failedUpdateMenu, true); - sd_obj.runUpdate(); - });*/ #endif this->addNodes(&deviceMenu, "Save/Load Files", TFTCYAN, NULL, SD_UPDATE, [this]() { this->changeMenu(&saveFileMenu, true); }); - this->addNodes(&deviceMenu, text_table1[16], TFTGREEN, NULL, LANGUAGE, [this]() { - - wifi_scan_obj.currentScanMode = SHOW_INFO; - this->changeMenu(&languageMenu, true); - }); this->addNodes(&deviceMenu, text_table1[17], TFTWHITE, NULL, DEVICE_INFO, [this]() { wifi_scan_obj.currentScanMode = SHOW_INFO; this->changeMenu(&infoMenu, true); @@ -3378,17 +2582,6 @@ void MenuFunctions::RunSetup() } #endif - /*#ifdef HAS_SD - //#ifndef HAS_ILI9341 - #ifdef HAS_BUTTONS - sdDeleteMenu.parentMenu = &deviceMenu; - this->addNodes(&sdDeleteMenu, text09, TFTLIGHTGREY, NULL, 0, [this]() { - this->changeMenu(sdDeleteMenu.parentMenu); - }); - #endif - //#endif - #endif*/ - // Save Files Menu saveFileMenu.parentMenu = &deviceMenu; this->addNodes(&saveFileMenu, text09, TFTLIGHTGREY, NULL, 0, [this]() { @@ -3490,10 +2683,6 @@ void MenuFunctions::RunSetup() this->changeMenu(gpsPOIMenu.parentMenu, true); }); this->addNodes(&gpsPOIMenu, "Mark POI", TFTCYAN, NULL, GPS_MENU, [this]() { - /*if (wifi_scan_obj.currentScanMode != GPS_POI) { - wifi_scan_obj.currentScanMode = GPS_POI; - wifi_scan_obj.StartScan(GPS_POI, TFT_CYAN); - }*/ wifi_scan_obj.currentScanMode = GPS_POI; display_obj.tft.setCursor(0, TFT_HEIGHT / 2); display_obj.clearScreen(); @@ -3503,7 +2692,6 @@ void MenuFunctions::RunSetup() display_obj.showCenterText("POI Log Failed", TFT_HEIGHT / 2); wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF; delay(2000); - //wifi_scan_obj.StartScan(WIFI_SCAN_OFF); this->changeMenu(&gpsPOIMenu, true); }); @@ -3542,13 +2730,6 @@ void MenuFunctions::RunSetup() addNodes(&specSettingMenu, text09, TFTLIGHTGREY, NULL, 0, [this]() { this->changeMenu(specSettingMenu.parentMenu, true); }); - - // Select update - /*whichUpdateMenu.parentMenu = &deviceMenu; - this->addNodes(&whichUpdateMenu, text09, TFTLIGHTGREY, NULL, 0, [this]() { - wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF; - this->changeMenu(whichUpdateMenu.parentMenu, true); - });*/ // Web Update updateMenu.parentMenu = &deviceMenu; @@ -3566,12 +2747,7 @@ void MenuFunctions::RunSetup() wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF; this->changeMenu(infoMenu.parentMenu, true); }); - //language info menu - languageMenu.parentMenu = &deviceMenu; - this->addNodes(&languageMenu, text09, TFTLIGHTGREY, NULL, 0, [this]() { - wifi_scan_obj.currentScanMode = WIFI_SCAN_OFF; - this->changeMenu(infoMenu.parentMenu, true); - }); + // Set the current menu to the mainMenu this->changeMenu(&mainMenu, true); @@ -3579,6 +2755,7 @@ void MenuFunctions::RunSetup() } //#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; @@ -3982,7 +3159,7 @@ void MenuFunctions::RunSetup() //#endif #endif } -//#endif +#endif void MenuFunctions::setupSDFileList(bool update) { sd_obj.sd_files->clear(); @@ -4023,8 +3200,6 @@ void MenuFunctions::buildSDFileMenu(bool update) { 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) + "..."); - //sd_obj.sd_files->remove(x); - //sdDeleteMenu.list->remove(x + 1); // +1 for "Back" this->buildSDFileMenu(); this->changeMenu(&sdDeleteMenu, true); } @@ -4051,7 +3226,7 @@ void MenuFunctions::showMenuList(Menu * menu, int layer) // Depending on layer, indent for (uint8_t x = 0; x < layer * 4; x++) Serial.print(" "); - Serial.print("Node: "); + Serial.print(F("Node: ")); Serial.println(menu->list->get(i).name); } Serial.println(); @@ -4059,18 +3234,10 @@ 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 callable, bool selected, String command) -{ - TFT_eSPI_Button new_button; - menu->list->add(MenuNode{name, false, color, place, &new_button, selected, callable}); - //menu->list->add(MenuNode{name, false, color, place, selected, callable}); -}*/ - void MenuFunctions::addNodes(Menu * menu, String name, uint8_t color, Menu * child, int place, std::function callable, bool selected, String command) { TFT_eSPI_Button new_button; menu->list->add(MenuNode{name, false, color, place, &new_button, selected, callable}); - //menu->list->add(MenuNode{name, false, color, place, selected, callable}); } void MenuFunctions::setGraphScale(float scale) { @@ -4372,29 +3539,18 @@ void MenuFunctions::displayCurrentMenu(int start_index) display_obj.tft.setTextSize(1); #endif - // Draw the up, down, select buttons - /*#ifdef HAS_ILI9341 - for (int i = BUTTON_ARRAY_LEN; i < BUTTON_ARRAY_LEN + 3; i++) { - display_obj.key[i].drawButton(true); - } - #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 - //#ifndef HAS_ILI9341 - if ((current_menu->list->get(i).selected) || (current_menu->selected == i)) { - display_obj.key[i - start_index].drawButton(true, current_menu->list->get(i).name); - } - else { - display_obj.key[i - start_index].drawButton(false, current_menu->list->get(i).name); - } - //#else - // display_obj.key[i].drawButton(false, current_menu->list->get(i).name); - //#endif + if ((current_menu->list->get(i).selected) || (current_menu->selected == i)) { + display_obj.key[i - start_index].drawButton(true, current_menu->list->get(i).name); + } + 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, diff --git a/esp32_marauder/MenuFunctions.h b/esp32_marauder/MenuFunctions.h index 036355a..dfc502a 100644 --- a/esp32_marauder/MenuFunctions.h +++ b/esp32_marauder/MenuFunctions.h @@ -9,6 +9,10 @@ #include "Keyboard.h" #endif +#ifdef HAS_TOUCH + #include "TouchKeyboard.h" +#endif + #ifdef HAS_SCREEN #define BATTERY_ANALOG_ON 0 @@ -95,41 +99,10 @@ extern Settings settings_obj; #define FUNNY_BEACON 40 #define FLOCK 41 -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 join_wifi_keyboard_event_cb(lv_obj_t * keyboard, lv_event_t event); -PROGMEM static void start_ap_keyboard_event_cb(lv_obj_t * keyboard, lv_event_t event); -PROGMEM static void add_ssid_keyboard_event_cb(lv_obj_t * keyboard, lv_event_t event); -PROGMEM static void html_list_cb(lv_obj_t * btn, lv_event_t event); -PROGMEM static void ap_list_cb(lv_obj_t * btn, lv_event_t event); -PROGMEM static void ap_info_list_cb(lv_obj_t * btn, lv_event_t event); -PROGMEM static void at_list_cb(lv_obj_t * btn, lv_event_t event); -PROGMEM static void station_list_cb(lv_obj_t * btn, lv_event_t event); -PROGMEM static void setting_dropdown_cb(lv_obj_t * btn, lv_event_t event); - -// lvgl stuff -PROGMEM static lv_obj_t *kb; -PROGMEM static lv_obj_t * save_as_kb; - struct Menu; // Individual Nodes of a menu -/*struct MenuNode { - String name; - bool command; - uint16_t color; - uint8_t icon; - TFT_eSPI_Button* button; - bool selected; - std::function callable; -};*/ - struct MenuNode { String name; bool command; @@ -175,13 +148,13 @@ class MenuFunctions Menu deviceMenu; // Device menu stuff - Menu whichUpdateMenu; + //Menu whichUpdateMenu; Menu failedUpdateMenu; Menu confirmMenu; Menu updateMenu; Menu settingsMenu; Menu specSettingMenu; - Menu languageMenu; + //Menu languageMenu; Menu sdDeleteMenu; // WiFi menu stuff @@ -195,9 +168,9 @@ class MenuFunctions Menu wifiAPMenu; Menu wifiIPMenu; Menu ssidsMenu; - #ifdef HAS_BT - Menu airtagMenu; - #endif + //#ifdef HAS_BT + // Menu airtagMenu; + //#endif //#ifndef HAS_ILI9341 Menu wifiStationMenu; //#endif @@ -253,7 +226,9 @@ class MenuFunctions void buttonSelected(int b, int x = -1); void buttonNotSelected(int b, int x = -1); //#if (!defined(HAS_ILI9341) && defined(HAS_BUTTONS)) + #ifdef HAS_MINI_KB String miniKeyboard(Menu * targetMenu, bool do_pass = false); + #endif //#endif #ifdef MARAUDER_CARDPUTER @@ -296,13 +271,8 @@ class MenuFunctions void joinWiFiGFX(String essid, bool start_ap = false); void setGraphScale(float scale); - void initLVGL(); - void deinitLVGL(); - void selectEPHTMLGFX(); void updateStatusBar(); void addSSIDGFX(); - void addAPGFX(String type = "AP"); - void addStationGFX(); void buildButtons(Menu* menu, int starting_index = 0, String button_name = ""); void changeMenu(Menu* menu, bool simple_change = false); void drawStatusBar(); diff --git a/esp32_marauder/SDInterface.cpp b/esp32_marauder/SDInterface.cpp index 131a0bc..a208af5 100644 --- a/esp32_marauder/SDInterface.cpp +++ b/esp32_marauder/SDInterface.cpp @@ -82,10 +82,10 @@ bool SDInterface::initSD() { } if (!SD.exists("/SCRIPTS")) { - Serial.println("/SCRIPTS does not exist. Creating..."); + Serial.println(F("/SCRIPTS does not exist. Creating...")); SD.mkdir("/SCRIPTS"); - Serial.println("/SCRIPTS created"); + Serial.println(F("/SCRIPTS created")); } this->sd_files = new LinkedList(); @@ -96,7 +96,7 @@ bool SDInterface::initSD() { } #else - Serial.println("SD support disabled, skipping init"); + Serial.println(F("SD support disabled, skipping init")); return false; #endif } @@ -280,7 +280,7 @@ void SDInterface::performUpdate(Stream &updateSource, size_t updateSize) { display_obj.tft.setTextColor(TFT_RED); display_obj.tft.println(text_table2[12]); #endif - Serial.println("Update not finished? Something went wrong!"); + Serial.println(F("Update not finished? Something went wrong!")); #ifdef HAS_SCREEN display_obj.tft.setTextColor(TFT_WHITE); #endif @@ -299,7 +299,7 @@ void SDInterface::performUpdate(Stream &updateSource, size_t updateSize) { #ifdef HAS_SCREEN display_obj.tft.println(text_table2[14]); #endif - Serial.println("Not enough space to begin OTA"); + Serial.println(F("Not enough space to begin OTA")); } } diff --git a/esp32_marauder/TouchKeyboard.cpp b/esp32_marauder/TouchKeyboard.cpp new file mode 100644 index 0000000..097b191 --- /dev/null +++ b/esp32_marauder/TouchKeyboard.cpp @@ -0,0 +1,402 @@ +#include "TouchKeyboard.h" +#include +#include + +#ifdef HAS_TOUCH + +extern Display display_obj; + +// Keyboard will occupy the bottom half of the screen. +static inline int16_t kbHeight() { return TFT_HEIGHT / 2; } +static inline int16_t kbYStart() { return TFT_HEIGHT - kbHeight(); } +static inline int16_t kbWidth() { return TFT_WIDTH; } +static inline int16_t kbXStart() { return 0; } + +static const int KEY_ROWS = 5; + +static const char ROW0_ALPHA[] = "1234567890"; +static const char ROW1_ALPHA[] = "qwertyuiop"; +static const char ROW2_ALPHA[] = "asdfghjkl"; +static const char ROW3_ALPHA[] = "zxcvbnm."; + +static const char ROW0_SYM[] = "!@#$%^&*()"; +static const char ROW1_SYM[] = "`~-_=+[]{}"; +static const char ROW2_SYM[] = "\\|;:'\""; +static const char ROW3_SYM[] = ",.<>/?"; + +static const uint16_t TOUCH_THRESHOLD = 600; + +enum KeyboardLayout { + LAYOUT_ALPHA = 0, + LAYOUT_SYMBOLS +}; + +static void drawTextArea(const char *title, const char *buffer) { + int16_t areaHeight = TFT_HEIGHT - kbHeight(); + + // Clear text area + display_obj.tft.fillRect(0, 0, TFT_WIDTH, areaHeight, TFT_BLACK); + + int16_t cursorY = 2; + + // Optional title + if (title && title[0] != '\0') { + display_obj.tft.setCursor(2, cursorY); + display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK); + display_obj.tft.print(title); + cursorY += 16; + } + + // Draw current text + display_obj.tft.setCursor(2, cursorY); + display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK); + display_obj.tft.print(buffer ? buffer : ""); +} + +static void drawKeyboard(KeyboardLayout layout, bool caps) { + const int16_t kY = kbYStart(); + const int16_t kH = kbHeight(); + const int16_t kX = kbXStart(); + const int16_t kW = kbWidth(); + + const int maxCols = 10; + const int rows = KEY_ROWS; + + const int16_t cellW = kW / maxCols; + const int16_t cellH = kH / rows; + + display_obj.tft.fillRect(kX, kY, kW, kH, TFT_DARKGREY); + display_obj.tft.setTextColor(TFT_BLACK, TFT_DARKGREY); + + // Choose row strings based on layout + const char *rowStringsAlpha[4] = { + ROW0_ALPHA, ROW1_ALPHA, ROW2_ALPHA, ROW3_ALPHA + }; + const char *rowStringsSym[4] = { + ROW0_SYM, ROW1_SYM, ROW2_SYM, ROW3_SYM + }; + + const char **rowsPtr = (layout == LAYOUT_ALPHA) + ? (const char **)rowStringsAlpha + : (const char **)rowStringsSym; + + // Draw normal character rows (0–3) + for (int r = 0; r < 4; ++r) { + const char *row = rowsPtr[r]; + + // For alpha layout row 3, we will also draw CAPS on the rightmost 2 columns. + // The textual row only covers the first part. + int rowLen = strlen(row); + + int16_t rowY = kY + r * cellH; + + // For alpha row 3, we want row chars towards the left, leaving space for CAPS. + int16_t xOffset; + if (layout == LAYOUT_ALPHA && r == 3) { + // Use columns 0..7 for characters, 8..9 for CAPS + xOffset = 0; + } else { + int maxColsRow = maxCols; + xOffset = (maxColsRow - rowLen); + if (xOffset < 0) xOffset = 0; + xOffset = (xOffset * cellW) / 2; // center row + } + + for (int i = 0; i < rowLen; ++i) { + int16_t keyX = kX + xOffset + i * cellW; + int16_t keyY = rowY; + + // Key border + display_obj.tft.drawRect(keyX, keyY, cellW, cellH, TFT_BLACK); + + // Label + display_obj.tft.setCursor(keyX + cellW / 2 - 3, keyY + cellH / 2 - 4); + char c = row[i]; + + // Apply CAPS on alpha letters + if (layout == LAYOUT_ALPHA && r > 0) { + if (c >= 'a' && c <= 'z') { + if (caps) { + c = (char)(c - 'a' + 'A'); + } + } + } + + char s[2] = { c, '\0' }; + display_obj.tft.print(s); + } + + // Draw CAPS key for alpha layout on row 3 (rightmost two columns) + if (layout == LAYOUT_ALPHA && r == 3) { + int16_t capsX = kX + 8 * cellW; + int16_t capsW = 2 * cellW; + + display_obj.tft.drawRect(capsX, rowY, capsW, cellH, TFT_BLACK); + display_obj.tft.setCursor(capsX + 4, rowY + cellH / 2 - 4); + // Show different label based on state + if (caps) { + display_obj.tft.print("caps"); + } else { + display_obj.tft.print("CAPS"); + } + } + } + + // Special row (row index 4): CANCEL | SYMB/ABC | SPACE | BKSP | OK + int r = 4; + int16_t rowY = kY + r * cellH; + + // Divide width into 6 segments: + // [CANCEL][SYMB][SPACE (2 segments)][BKSP][OK] + int16_t segW = kW / 6; + int16_t x0 = kX; + int16_t x1 = x0 + segW; // end CANCEL + int16_t x2 = x1 + segW; // end SYMB + int16_t x3 = x2 + 2 * segW; // end SPACE + int16_t x4 = x3 + segW; // end BKSP + int16_t x5 = x4 + segW; // end OK + + // CANCEL + display_obj.tft.drawRect(x0, rowY, segW, cellH, TFT_BLACK); + display_obj.tft.setCursor(x0 + 4, rowY + cellH / 2 - 4); + display_obj.tft.print("CANCEL"); + + // SYMB / ABC + display_obj.tft.drawRect(x1, rowY, segW, cellH, TFT_BLACK); + display_obj.tft.setCursor(x1 + 4, rowY + cellH / 2 - 4); + if (layout == LAYOUT_ALPHA) { + display_obj.tft.print("SYMB"); + } else { + display_obj.tft.print("ABC"); + } + + display_obj.tft.drawRect(x2, rowY, (x3 - x2), cellH, TFT_BLACK); + display_obj.tft.setCursor(x2 + 4, rowY + cellH / 2 - 4); + display_obj.tft.print("SPACE"); + + display_obj.tft.drawRect(x3, rowY, (x4 - x3), cellH, TFT_BLACK); + display_obj.tft.setCursor(x3 + 4, rowY + cellH / 2 - 4); + display_obj.tft.print("BKSP"); + + display_obj.tft.drawRect(x4, rowY, (x5 - x4), cellH, TFT_BLACK); + display_obj.tft.setCursor(x4 + 4, rowY + cellH / 2 - 4); + display_obj.tft.print("OK"); +} + +static bool appendChar(char *buffer, size_t bufLen, char c) { + size_t len = strlen(buffer); + if (len + 1 < bufLen) { + buffer[len] = c; + buffer[len + 1] = '\0'; + return true; + } + return false; +} + +static KeyboardResult handleKeyboardTouch(uint16_t tx, uint16_t ty, + char *buffer, size_t bufLen, + KeyboardLayout layout, + bool caps) { + if (!buffer || bufLen < 2) return KB_NONE; + + const int16_t kY = kbYStart(); + const int16_t kH = kbHeight(); + const int16_t kX = kbXStart(); + const int16_t kW = kbWidth(); + + if (ty < kY || ty >= (kY + kH)) { + // Touch is outside keyboard area + return KB_NONE; + } + + const int maxCols = 10; + const int rows = KEY_ROWS; + const int16_t cellW = kW / maxCols; + const int16_t cellH = kH / rows; + + int rowIndex = (ty - kY) / cellH; + + // Choose row strings based on layout + const char *rowStringsAlpha[4] = { + ROW0_ALPHA, ROW1_ALPHA, ROW2_ALPHA, ROW3_ALPHA + }; + const char *rowStringsSym[4] = { + ROW0_SYM, ROW1_SYM, ROW2_SYM, ROW3_SYM + }; + + const char **rowsPtr = (layout == LAYOUT_ALPHA) + ? (const char **)rowStringsAlpha + : (const char **)rowStringsSym; + + // Normal rows (0..3) + if (rowIndex >= 0 && rowIndex <= 3) { + const char *row = rowsPtr[rowIndex]; + int rowLen = strlen(row); + + int16_t rowY = kY + rowIndex * cellH; + + // Alpha row 3: characters on columns 0..7, CAPS on columns 8..9 + if (layout == LAYOUT_ALPHA && rowIndex == 3) { + int16_t capsXStart = kX + 8 * cellW; + int16_t capsXEnd = capsXStart + 2 * cellW; + + // Check CAPS region + if (tx >= capsXStart && tx < capsXEnd) { + return KB_TOGGLE_CAPS; + } + + // Characters only in the columns before CAPS + int16_t xOffset = 0; + if (tx < kX || tx >= (kX + 8 * cellW)) { + return KB_NONE; + } + + int colIndex = (tx - (kX + xOffset)) / cellW; + if (colIndex < 0 || colIndex >= rowLen) return KB_NONE; + + char c = row[colIndex]; + // Apply caps mapping + if (c >= 'a' && c <= 'z' && caps) { + c = (char)(c - 'a' + 'A'); + } + + if (appendChar(buffer, bufLen, c)) { + return KB_CHANGED; + } + return KB_NONE; + } + + // All other rows + int16_t xOffset = (maxCols - rowLen); + if (xOffset < 0) xOffset = 0; + xOffset = (xOffset * cellW) / 2; + + if (tx < kX + xOffset || tx >= kX + xOffset + rowLen * cellW) { + return KB_NONE; + } + + int colIndex = (tx - (kX + xOffset)) / cellW; + if (colIndex < 0 || colIndex >= rowLen) return KB_NONE; + + char c = row[colIndex]; + + // Apply caps on alpha letters (rows 1 and 2) + if (layout == LAYOUT_ALPHA && rowIndex > 0) { + if (c >= 'a' && c <= 'z' && caps) { + c = (char)(c - 'a' + 'A'); + } + } + + if (appendChar(buffer, bufLen, c)) { + return KB_CHANGED; + } + return KB_NONE; + } + + // Special row (rowIndex == 4): CANCEL | SYMB/ABC | SPACE | BKSP | OK + if (rowIndex == 4) { + int16_t rowY = kY + rowIndex * cellH; + + int16_t segW = kW / 6; + int16_t x0 = kX; + int16_t x1 = x0 + segW; // end CANCEL + int16_t x2 = x1 + segW; // end SYMB + int16_t x3 = x2 + 2 * segW; // end SPACE + int16_t x4 = x3 + segW; // end BKSP + int16_t x5 = x4 + segW; // end OK + + // CANCEL + if (tx >= x0 && tx < x1) { + return KB_CANCEL; + } + + // SYMB / ABC toggle + if (tx >= x1 && tx < x2) { + return KB_TOGGLE_LAYOUT; + } + + // SPACE (x2..x3) + if (tx >= x2 && tx < x3) { + if (appendChar(buffer, bufLen, ' ')) { + return KB_CHANGED; + } + return KB_NONE; + } + + // BKSP (x3..x4) + if (tx >= x3 && tx < x4) { + size_t len = strlen(buffer); + if (len > 0) { + buffer[len - 1] = '\0'; + return KB_CHANGED; + } + return KB_NONE; + } + + // OK (x4..x5) + if (tx >= x4 && tx < x5) { + return KB_DONE; + } + } + + return KB_NONE; +} + + +bool keyboardInput(char *buffer, size_t bufLen, const char *title) { + if (!buffer || bufLen < 2) { + return false; + } + + // To force clear, uncomment this: + // buffer[0] = '\0'; + + KeyboardLayout layout = LAYOUT_ALPHA; + bool caps = false; + + drawTextArea(title, buffer); + drawKeyboard(layout, caps); + + uint32_t lastTouchTime = 0; + const uint32_t debounceMs = 120; + + while (true) { + uint16_t x = 0, y = 0; + uint8_t touched = display_obj.updateTouch(&x, &y, TOUCH_THRESHOLD); + + if (touched) { + uint32_t now = millis(); + if (now - lastTouchTime < debounceMs) { + // "debounce" + continue; + } + lastTouchTime = now; + + KeyboardResult r = handleKeyboardTouch(x, y, buffer, bufLen, layout, caps); + + if (r == KB_CHANGED) { + drawTextArea(title, buffer); + } else if (r == KB_DONE) { + drawTextArea(title, buffer); + return true; + } else if (r == KB_CANCEL) { + // Optional: buffer[0] = '\0'; + drawTextArea(title, buffer); + return false; + } else if (r == KB_TOGGLE_LAYOUT) { + layout = (layout == LAYOUT_ALPHA) ? LAYOUT_SYMBOLS : LAYOUT_ALPHA; + drawKeyboard(layout, caps); + } else if (r == KB_TOGGLE_CAPS) { + caps = !caps; + drawKeyboard(layout, caps); + } + } + + delay(5); + yield(); + } + + return false; +} + +#endif \ No newline at end of file diff --git a/esp32_marauder/TouchKeyboard.h b/esp32_marauder/TouchKeyboard.h new file mode 100644 index 0000000..ae744db --- /dev/null +++ b/esp32_marauder/TouchKeyboard.h @@ -0,0 +1,31 @@ +#pragma once + +#include "configs.h" + +#ifdef HAS_TOUCH + +#include "Display.h" +#include +#include + +enum KeyboardResult { + KB_NONE = 0, + KB_CHANGED, + KB_DONE, + KB_CANCEL, + KB_TOGGLE_LAYOUT, + KB_TOGGLE_CAPS +}; + +/** + * Blocking keyboard input. + * + * @param buffer Caller-provided char buffer to hold the text. Will be null-terminated. + * @param bufLen Total size of the buffer (including space for '\0'). + * @param title Optional title displayed above the text box (can be nullptr). + * + * @return true if user pressed OK, false if user pressed CANCEL (or if buffer invalid). + */ +bool keyboardInput(char *buffer, size_t bufLen, const char *title = nullptr); + +#endif \ No newline at end of file diff --git a/esp32_marauder/WiFiScan.cpp b/esp32_marauder/WiFiScan.cpp index cd1cc42..26995fb 100644 --- a/esp32_marauder/WiFiScan.cpp +++ b/esp32_marauder/WiFiScan.cpp @@ -62,7 +62,11 @@ extern "C" { memcpy(&AdvData_Raw[i], Name, name_len); i += name_len; - AdvData.addData(std::string((char *)AdvData_Raw, 7 + name_len)); + #ifndef HAS_DUAL_BAND + AdvData.addData(std::string((char *)AdvData_Raw, 7 + name_len)); + #else + AdvData.addData(AdvData_Raw, 7 + name_len); + #endif break; } case Apple: { @@ -84,7 +88,11 @@ extern "C" { AdvData_Raw[i++] = 0x10; // Type ??? esp_fill_random(&AdvData_Raw[i], 3); - AdvData.addData(std::string((char *)AdvData_Raw, 17)); + #ifndef HAS_DUAL_BAND + AdvData.addData(std::string((char *)AdvData_Raw, 17)); + #else + AdvData.addData(AdvData_Raw, 17); + #endif break; } case Samsung: { @@ -109,7 +117,11 @@ extern "C" { AdvData_Raw[i++] = 0x43; AdvData_Raw[i++] = (model >> 0x00) & 0xFF; // Watch Model / Color (?) - AdvData.addData(std::string((char *)AdvData_Raw, 15)); + #ifndef HAS_DUAL_BAND + AdvData.addData(std::string((char *)AdvData_Raw, 15)); + #else + AdvData.addData(AdvData_Raw, 15); + #endif break; } @@ -132,7 +144,11 @@ extern "C" { AdvData_Raw[i++] = 0x0A; AdvData_Raw[i++] = (rand() % 120) - 100; // -100 to +20 dBm - AdvData.addData(std::string((char *)AdvData_Raw, 14)); + #ifndef HAS_DUAL_BAND + AdvData.addData(std::string((char *)AdvData_Raw, 14)); + #else + AdvData.addData(AdvData_Raw, 14); + #endif break; } case FlipperZero: { @@ -180,7 +196,11 @@ extern "C" { AdvData_Raw[i++] = 0x80; // Add the constructed Advertisement Data to the BLE advertisement - AdvData.addData(std::string((char *)AdvData_Raw, i)); + #ifndef HAS_DUAL_BAND + AdvData.addData(std::string((char *)AdvData_Raw, i)); + #else + AdvData.addData(AdvData_Raw, i); + #endif break; } @@ -188,7 +208,11 @@ extern "C" { case Airtag: { for (int i = 0; i < airtags->size(); i++) { if (airtags->get(i).selected) { - AdvData.addData(std::string((char*)airtags->get(i).payload.data(), airtags->get(i).payloadSize)); + #ifndef HAS_DUAL_BAND + AdvData.addData(std::string((char*)airtags->get(i).payload.data(), airtags->get(i).payloadSize)); + #else + AdvData.addData(airtags->get(i).payload.data(), airtags->get(i).payloadSize); + #endif break; } @@ -197,7 +221,7 @@ extern "C" { break; } default: { - Serial.println("Please Provide a Company Type"); + Serial.println(F("Please Provide a Company Type")); break; } } @@ -209,653 +233,1441 @@ extern "C" { //// https://github.com/Spooks4576 - class bluetoothScanAllCallback: public NimBLEAdvertisedDeviceCallbacks { - - void onResult(NimBLEAdvertisedDevice *advertisedDevice) { + #ifndef HAS_DUAL_BAND + class bluetoothScanAllCallback: public NimBLEAdvertisedDeviceCallbacks { + + void onResult(NimBLEAdvertisedDevice *advertisedDevice) { - extern WiFiScan wifi_scan_obj; - - //#ifdef HAS_SCREEN - // int buf = display_obj.display_buffer->size(); - //#else - int buf = 0; - //#endif - - String display_string = ""; + extern WiFiScan wifi_scan_obj; + + //#ifdef HAS_SCREEN + // int buf = display_obj.display_buffer->size(); + //#else + int buf = 0; + //#endif + + String display_string = ""; - if ((wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG) || - (wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG_MON)) { - uint8_t* payLoad = advertisedDevice->getPayload(); - size_t len = advertisedDevice->getPayloadLength(); + if ((wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG) || + (wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG_MON)) { + #ifndef HAS_DUAL_BAND + uint8_t* payLoad = advertisedDevice->getPayload(); + size_t len = advertisedDevice->getPayloadLength(); + #else + const std::vector& payLoad = advertisedDevice->getPayload(); + size_t len = payLoad.size(); + #endif - bool match = false; - for (int i = 0; i <= len - 4; i++) { - if (payLoad[i] == 0x1E && payLoad[i+1] == 0xFF && payLoad[i+2] == 0x4C && payLoad[i+3] == 0x00) { - match = true; - break; - } - if (payLoad[i] == 0x4C && payLoad[i+1] == 0x00 && payLoad[i+2] == 0x12 && payLoad[i+3] == 0x19) { - match = true; - break; - } - } - - int rssi = advertisedDevice->getRSSI(); - - if (match) { - String mac = advertisedDevice->getAddress().toString().c_str(); - mac.toUpperCase(); - - for (int i = 0; i < airtags->size(); i++) { - // Airtag is in list already. Update RSSI - if (mac == airtags->get(i).mac) { - AirTag old_airtag = airtags->get(i); - old_airtag.rssi = rssi; - old_airtag.last_seen = millis(); - airtags->set(i, old_airtag); - return; + bool match = false; + for (int i = 0; i <= len - 4; i++) { + if (payLoad[i] == 0x1E && payLoad[i+1] == 0xFF && payLoad[i+2] == 0x4C && payLoad[i+3] == 0x00) { + match = true; + break; + } + if (payLoad[i] == 0x4C && payLoad[i+1] == 0x00 && payLoad[i+2] == 0x12 && payLoad[i+3] == 0x19) { + match = true; + break; } } - Serial.print("RSSI: "); - Serial.print(rssi); - Serial.print(" MAC: "); - Serial.println(mac); - Serial.print("Len: "); - Serial.print(len); - Serial.print(" Payload: "); - for (size_t i = 0; i < len; i++) { - Serial.printf("%02X ", payLoad[i]); + int rssi = advertisedDevice->getRSSI(); + + if (match) { + String mac = advertisedDevice->getAddress().toString().c_str(); + mac.toUpperCase(); + + for (int i = 0; i < airtags->size(); i++) { + // Airtag is in list already. Update RSSI + if (mac == airtags->get(i).mac) { + AirTag old_airtag = airtags->get(i); + old_airtag.rssi = rssi; + old_airtag.last_seen = millis(); + airtags->set(i, old_airtag); + return; + } + } + + Serial.print(F("RSSI: ")); + Serial.print(rssi); + Serial.print(F(" MAC: ")); + Serial.println(mac); + Serial.print(F("Len: ")); + Serial.print(len); + Serial.print(F(" Payload: ")); + for (size_t i = 0; i < len; i++) { + Serial.printf("%02X ", payLoad[i]); + } + Serial.println("\n"); + + AirTag airtag; + airtag.mac = mac; + airtag.payload.assign(payLoad, payLoad + len); + airtag.payloadSize = len; + airtag.rssi = rssi; + airtag.last_seen = millis(); + + airtags->add(airtag); + + + if (wifi_scan_obj.currentScanMode != BT_SCAN_AIRTAG_MON) { + #ifdef HAS_SCREEN + //display_string.concat("RSSI: "); + display_string.concat((String)rssi); + display_string.concat(" MAC: "); + display_string.concat(mac); + uint8_t temp_len = display_string.length(); + for (uint8_t i = 0; i < 40 - temp_len; i++) + { + display_string.concat(" "); + } + display_obj.display_buffer->add(display_string); + #endif + } } - Serial.println("\n"); + } + else if (wifi_scan_obj.currentScanMode == BT_SCAN_FLIPPER) { + #ifndef HAS_DUAL_BAND + uint8_t* payLoad = advertisedDevice->getPayload(); + size_t len = advertisedDevice->getPayloadLength(); + #else + const std::vector& payLoad = advertisedDevice->getPayload(); + size_t len = payLoad.size(); + #endif - AirTag airtag; - airtag.mac = mac; - airtag.payload.assign(payLoad, payLoad + len); - airtag.payloadSize = len; - airtag.rssi = rssi; - airtag.last_seen = millis(); + bool match = false; + String color = ""; + for (int i = 0; i <= len - 4; i++) { + if (payLoad[i] == 0x81 && payLoad[i+1] == 0x30) { + match = true; + color = "Black"; + break; + } + if (payLoad[i] == 0x82 && payLoad[i+1] == 0x30) { + match = true; + color = "White"; + break; + } + if (payLoad[i] == 0x83 && payLoad[i+1] == 0x30) { + color = "Transparent"; + match = true; + break; + } + } - airtags->add(airtag); + if (match) { + String mac = advertisedDevice->getAddress().toString().c_str(); + String name = advertisedDevice->getName().c_str(); + mac.toUpperCase(); + for (int i = 0; i < flippers->size(); i++) { + if (mac == flippers->get(i).mac) + return; + } + + int rssi = advertisedDevice->getRSSI(); + Serial.print(F("RSSI: ")); + Serial.print(rssi); + Serial.print(F(" MAC: ")); + Serial.println(mac); + Serial.print(F("Name: ")); + Serial.println(name); + + Flipper flipper; + flipper.mac = mac; + flipper.name = name; + + flippers->add(flipper); - if (wifi_scan_obj.currentScanMode != BT_SCAN_AIRTAG_MON) { #ifdef HAS_SCREEN - //display_string.concat("RSSI: "); - display_string.concat((String)rssi); - display_string.concat(" MAC: "); - display_string.concat(mac); + display_obj.display_buffer->add(String("Flipper: ") + name + ", "); + display_obj.display_buffer->add(" MAC: " + String(mac) + ", "); + display_obj.display_buffer->add(" RSSI: " + String(rssi) + ", "); + display_obj.display_buffer->add(" Color: " + String(color) + " "); + #endif + } + } + else if (wifi_scan_obj.currentScanMode == BT_SCAN_ALL) { + if (buf >= 0) + { + display_string.concat(text_table4[0]); + display_string.concat(advertisedDevice->getRSSI()); + Serial.print(F(" RSSI: ")); + Serial.print(advertisedDevice->getRSSI()); + + display_string.concat(" "); + Serial.print(" "); + + Serial.print(F("Device: ")); + if(advertisedDevice->getName().length() != 0) + { + 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()); + } + + #ifdef HAS_SCREEN uint8_t temp_len = display_string.length(); for (uint8_t i = 0; i < 40 - temp_len; i++) { display_string.concat(" "); } - display_obj.display_buffer->add(display_string); - #endif - } - } - } - else if (wifi_scan_obj.currentScanMode == BT_SCAN_FLIPPER) { - uint8_t* payLoad = advertisedDevice->getPayload(); - size_t len = advertisedDevice->getPayloadLength(); - - bool match = false; - String color = ""; - for (int i = 0; i <= len - 4; i++) { - if (payLoad[i] == 0x81 && payLoad[i+1] == 0x30) { - match = true; - color = "Black"; - break; - } - if (payLoad[i] == 0x82 && payLoad[i+1] == 0x30) { - match = true; - color = "White"; - break; - } - if (payLoad[i] == 0x83 && payLoad[i+1] == 0x30) { - color = "Transparent"; - match = true; - break; - } - } - - if (match) { - String mac = advertisedDevice->getAddress().toString().c_str(); - String name = advertisedDevice->getName().c_str(); - mac.toUpperCase(); - - for (int i = 0; i < flippers->size(); i++) { - if (mac == flippers->get(i).mac) - return; - } - - int rssi = advertisedDevice->getRSSI(); - Serial.print("RSSI: "); - Serial.print(rssi); - Serial.print(" MAC: "); - Serial.println(mac); - Serial.print("Name: "); - Serial.println(name); - - Flipper flipper; - flipper.mac = mac; - flipper.name = name; - - flippers->add(flipper); - - #ifdef HAS_SCREEN - display_obj.display_buffer->add(String("Flipper: ") + name + ", "); - display_obj.display_buffer->add(" MAC: " + String(mac) + ", "); - display_obj.display_buffer->add(" RSSI: " + String(rssi) + ", "); - display_obj.display_buffer->add(" Color: " + String(color) + " "); - #endif - } - } - else if (wifi_scan_obj.currentScanMode == BT_SCAN_ALL) { - if (buf >= 0) - { - display_string.concat(text_table4[0]); - display_string.concat(advertisedDevice->getRSSI()); - Serial.print(" RSSI: "); - Serial.print(advertisedDevice->getRSSI()); - - display_string.concat(" "); - Serial.print(" "); - - Serial.print("Device: "); - if(advertisedDevice->getName().length() != 0) - { - 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()); - } - - #ifdef HAS_SCREEN - uint8_t temp_len = display_string.length(); - for (uint8_t i = 0; i < 40 - temp_len; i++) - { - display_string.concat(" "); - } - - Serial.println(); - - while (display_obj.printing) - delay(1); - display_obj.loading = true; - display_obj.display_buffer->add(display_string); - display_obj.loading = false; - #endif - } - } - else if ((wifi_scan_obj.currentScanMode == BT_SCAN_WAR_DRIVE) || (wifi_scan_obj.currentScanMode == BT_SCAN_WAR_DRIVE_CONT)) { - #ifdef HAS_GPS - if (gps_obj.getGpsModuleStatus()) { - bool do_save = false; - if (buf >= 0) - { - Serial.print("Device: "); - if(advertisedDevice->getName().length() != 0) - { - 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()); - } - - if (gps_obj.getFixStatus()) { - do_save = true; - display_string.concat(" | Lt: " + gps_obj.getLat()); - display_string.concat(" | Ln: " + gps_obj.getLon()); - } - else { - display_string.concat(" | GPS: No Fix"); - } - #ifdef HAS_SCREEN - uint8_t temp_len = display_string.length(); - for (uint8_t i = 0; i < 40 - temp_len; i++) - { - display_string.concat(" "); - } - - Serial.println(); - - while (display_obj.printing) - delay(1); - display_obj.loading = true; - display_obj.display_buffer->add(display_string); - display_obj.loading = false; - #endif - - String wardrive_line = (String)advertisedDevice->getAddress().toString().c_str() + ",,[BLE]," + gps_obj.getDatetime() + ",0," + (String)advertisedDevice->getRSSI() + "," + gps_obj.getLat() + "," + gps_obj.getLon() + "," + gps_obj.getAlt() + "," + gps_obj.getAccuracy() + ",BLE\n"; - Serial.print(wardrive_line); - - if (do_save) - buffer_obj.append(wardrive_line); - } - } - #endif - } - else if (wifi_scan_obj.currentScanMode == BT_SCAN_ANALYZER) { - wifi_scan_obj._analyzer_value++; - - if (wifi_scan_obj.analyzer_frames_recvd < 254) - wifi_scan_obj.analyzer_frames_recvd++; - - if (wifi_scan_obj.analyzer_frames_recvd > ANALYZER_NAME_REFRESH) { - display_string.concat(advertisedDevice->getRSSI()); - display_string.concat(" "); - - if(advertisedDevice->getName().length() != 0) - display_string.concat(advertisedDevice->getName().c_str()); - else - display_string.concat(advertisedDevice->getAddress().toString().c_str()); - - wifi_scan_obj.analyzer_frames_recvd = 0; - wifi_scan_obj.analyzer_name_string = display_string; - wifi_scan_obj.analyzer_name_update = true; - } - } - else if (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) { - uint8_t* payLoad = advertisedDevice->getPayload(); - size_t len = advertisedDevice->getPayloadLength(); - - bool hasXuntongMfg = false; - size_t mfgIndex = 0; // index of 0xFF (AD type) - - // Look for Company ID XUNTONG (0x09C8), - for (size_t i = 1; i + 3 < len; i++) { - if (payLoad[i] == 0xFF && // AD type: Manufacturer Specific - payLoad[i + 1] == 0xC8 && - payLoad[i + 2] == 0x09) { - hasXuntongMfg = true; - mfgIndex = i; - break; - } - } - - String name = advertisedDevice->getName().c_str(); - - // Check for old penguin name - bool penguin = false; - - if (name.length() > 0) { - // Old firmware: "Penguin-XXXXXXXXXX" - if (name.startsWith("Penguin-") && name.length() == 18) { - bool allDigits = true; - for (int i = 8; i < name.length(); i++) { - char c = name.charAt(i); - if (c < '0' || c > '9') { - allDigits = false; - break; - } - } - if (allDigits) { - penguin = true; - } - } - - // Legacy name: "FS Ext Battery" - if (name == "FS Ext Battery") { - penguin = true; - } - - // New firmware: "NNNNNNNNNN" (10 digits) - if (name.length() == 10) { - bool allDigits = true; - for (int i = 0; i < name.length(); i++) { - char c = name.charAt(i); - if (c < '0' || c > '9') { - allDigits = false; - break; - } - } - if (allDigits) { - penguin = true; - } - } - } - - // Try to extract serial number from the XUNTONG manufacturer data - String serial = ""; - - if (hasXuntongMfg && mfgIndex > 0) { - uint8_t adLen = payLoad[mfgIndex - 1]; // length byte for this AD structure - size_t adStart = mfgIndex - 1; - size_t adEnd = adStart + adLen; // exclusive end index - - if (adEnd > len) { - adEnd = len; - } - - size_t vendorStart = mfgIndex + 3; - if (vendorStart < adEnd) { - bool started = false; - - for (size_t k = vendorStart; k < adEnd; k++) { - char c = (char)payLoad[k]; - - if (!started) { - if (c == 'T' && (k + 1) < adEnd && (char)payLoad[k + 1] == 'N') { - started = true; - serial += 'T'; - serial += 'N'; - k++; - } - } else { - // Once started, append digits (skip separators; stop on anything else) - if (c >= '0' && c <= '9') { - serial += c; - } else if (c == ' ' || c == '#' || c == '-') { - continue; - } else { - break; - } - } - } - } - } - - // Final decision on marking as Flock Penguin battery - if (hasXuntongMfg && (penguin || name.length() == 0)) { - String mac = advertisedDevice->getAddress().toString().c_str(); - mac.toUpperCase(); - int rssi = advertisedDevice->getRSSI(); - - Serial.println("[FLOCK PENGUIN BATTERY CANDIDATE]"); - Serial.print(" RSSI: "); - Serial.println(rssi); - Serial.print(" MAC: "); - Serial.println(mac); - Serial.print(" Name: "); - Serial.println(name); - Serial.print(" Serial: "); - Serial.println(serial.length() ? serial : "N/A"); - - Serial.print(" Payload: "); - for (size_t i = 0; i < len; i++) { - Serial.printf("%02X ", payLoad[i]); - } - Serial.println(); - Serial.println(); - - #ifdef HAS_SCREEN - String display_string = ""; - display_string.concat(String(rssi)); - display_string.concat(" "); - if (serial.length()) { - display_string.concat(serial); - display_string.concat(" "); - } - - if (name.length() == 0) { - display_string.concat(" MAC:"); - display_string.concat(mac); - } - else { - display_string.concat(" "); - display_string.concat(name); - } - - uint8_t temp_len = display_string.length(); - for (uint8_t i = 0; i < 40 - temp_len; i++) { - display_string.concat(" "); - } - - if (!display_obj.printing) { + Serial.println(); + + while (display_obj.printing) + delay(1); display_obj.loading = true; display_obj.display_buffer->add(display_string); display_obj.loading = false; + #endif + } + } + else if ((wifi_scan_obj.currentScanMode == BT_SCAN_WAR_DRIVE) || (wifi_scan_obj.currentScanMode == BT_SCAN_WAR_DRIVE_CONT)) { + #ifdef HAS_GPS + if (gps_obj.getGpsModuleStatus()) { + bool do_save = false; + if (buf >= 0) + { + Serial.print(F("Device: ")); + if(advertisedDevice->getName().length() != 0) + { + 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()); + } + + if (gps_obj.getFixStatus()) { + do_save = true; + display_string.concat(" | Lt: " + gps_obj.getLat()); + display_string.concat(" | Ln: " + gps_obj.getLon()); + } + else { + display_string.concat(" | GPS: No Fix"); + } + + #ifdef HAS_SCREEN + uint8_t temp_len = display_string.length(); + for (uint8_t i = 0; i < 40 - temp_len; i++) + { + display_string.concat(" "); + } + + Serial.println(); + + while (display_obj.printing) + delay(1); + display_obj.loading = true; + display_obj.display_buffer->add(display_string); + display_obj.loading = false; + #endif + + String wardrive_line = (String)advertisedDevice->getAddress().toString().c_str() + ",,[BLE]," + gps_obj.getDatetime() + ",0," + (String)advertisedDevice->getRSSI() + "," + gps_obj.getLat() + "," + gps_obj.getLon() + "," + gps_obj.getAlt() + "," + gps_obj.getAccuracy() + ",BLE\n"; + Serial.print(wardrive_line); + + if (do_save) + buffer_obj.append(wardrive_line); + } } #endif - - // To-do: - // track in a list like AirTag / Flipper, if you want - // (struct FlockBattery { String mac; String name; String serial; int rssi; uint32_t last_seen; }; etc.) } - } - else if (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK_WARDRIVE) { - bool do_save = false; - #ifdef HAS_GPS - if (gps_obj.getGpsModuleStatus()) { + else if (wifi_scan_obj.currentScanMode == BT_SCAN_ANALYZER) { + wifi_scan_obj._analyzer_value++; - unsigned char mac_char[6]; - wifi_scan_obj.copyNimbleMac(advertisedDevice->getAddress(), mac_char); + if (wifi_scan_obj.analyzer_frames_recvd < 254) + wifi_scan_obj.analyzer_frames_recvd++; - if (wifi_scan_obj.seen_mac(mac_char)) - return; + if (wifi_scan_obj.analyzer_frames_recvd > ANALYZER_NAME_REFRESH) { + display_string.concat(advertisedDevice->getRSSI()); + display_string.concat(" "); + if(advertisedDevice->getName().length() != 0) + display_string.concat(advertisedDevice->getName().c_str()); + else + display_string.concat(advertisedDevice->getAddress().toString().c_str()); + + wifi_scan_obj.analyzer_frames_recvd = 0; + wifi_scan_obj.analyzer_name_string = display_string; + wifi_scan_obj.analyzer_name_update = true; + } + } + else if (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) { + #ifndef HAS_DUAL_BAND uint8_t* payLoad = advertisedDevice->getPayload(); size_t len = advertisedDevice->getPayloadLength(); + #else + const std::vector& payLoad = advertisedDevice->getPayload(); + size_t len = payLoad.size(); + #endif - bool hasXuntongMfg = false; - size_t mfgIndex = 0; // index of 0xFF (AD type) + bool hasXuntongMfg = false; + size_t mfgIndex = 0; // index of 0xFF (AD type) - // Look for Company ID XUNTONG (0x09C8), - for (size_t i = 1; i + 3 < len; i++) { - if (payLoad[i] == 0xFF && // AD type: Manufacturer Specific - payLoad[i + 1] == 0xC8 && - payLoad[i + 2] == 0x09) { - hasXuntongMfg = true; - mfgIndex = i; - break; - } + // Look for Company ID XUNTONG (0x09C8), + for (size_t i = 1; i + 3 < len; i++) { + if (payLoad[i] == 0xFF && // AD type: Manufacturer Specific + payLoad[i + 1] == 0xC8 && + payLoad[i + 2] == 0x09) { + hasXuntongMfg = true; + mfgIndex = i; + break; } + } - String name = advertisedDevice->getName().c_str(); + String name = advertisedDevice->getName().c_str(); - // Check for old penguin name - bool penguin = false; + // Check for old penguin name + bool penguin = false; - if (name.length() > 0) { - // Old firmware: "Penguin-XXXXXXXXXX" - if (name.startsWith("Penguin-") && name.length() == 18) { - bool allDigits = true; - for (int i = 8; i < name.length(); i++) { - char c = name.charAt(i); - if (c < '0' || c > '9') { - allDigits = false; - break; - } - } - if (allDigits) { - penguin = true; + if (name.length() > 0) { + // Old firmware: "Penguin-XXXXXXXXXX" + if (name.startsWith("Penguin-") && name.length() == 18) { + bool allDigits = true; + for (int i = 8; i < name.length(); i++) { + char c = name.charAt(i); + if (c < '0' || c > '9') { + allDigits = false; + break; } } - - // Legacy name: "FS Ext Battery" - if (name == "FS Ext Battery") { + if (allDigits) { penguin = true; } + } - // New firmware: "NNNNNNNNNN" (10 digits) - if (name.length() == 10) { - bool allDigits = true; - for (int i = 0; i < name.length(); i++) { - char c = name.charAt(i); - if (c < '0' || c > '9') { - allDigits = false; + // Legacy name: "FS Ext Battery" + if (name == "FS Ext Battery") { + penguin = true; + } + + // New firmware: "NNNNNNNNNN" (10 digits) + if (name.length() == 10) { + bool allDigits = true; + for (int i = 0; i < name.length(); i++) { + char c = name.charAt(i); + if (c < '0' || c > '9') { + allDigits = false; + break; + } + } + if (allDigits) { + penguin = true; + } + } + } + + // Try to extract serial number from the XUNTONG manufacturer data + String serial = ""; + + if (hasXuntongMfg && mfgIndex > 0) { + uint8_t adLen = payLoad[mfgIndex - 1]; // length byte for this AD structure + size_t adStart = mfgIndex - 1; + size_t adEnd = adStart + adLen; // exclusive end index + + if (adEnd > len) { + adEnd = len; + } + + size_t vendorStart = mfgIndex + 3; + if (vendorStart < adEnd) { + bool started = false; + + for (size_t k = vendorStart; k < adEnd; k++) { + char c = (char)payLoad[k]; + + if (!started) { + if (c == 'T' && (k + 1) < adEnd && (char)payLoad[k + 1] == 'N') { + started = true; + serial += 'T'; + serial += 'N'; + k++; + } + } else { + // Once started, append digits (skip separators; stop on anything else) + if (c >= '0' && c <= '9') { + serial += c; + } else if (c == ' ' || c == '#' || c == '-') { + continue; + } else { break; } } - if (allDigits) { - penguin = true; - } } } + } - // Try to extract serial number from the XUNTONG manufacturer data - String serial = ""; + // Final decision on marking as Flock Penguin battery + if (hasXuntongMfg && (penguin || name.length() == 0)) { + String mac = advertisedDevice->getAddress().toString().c_str(); + mac.toUpperCase(); + int rssi = advertisedDevice->getRSSI(); - if (hasXuntongMfg && mfgIndex > 0) { - uint8_t adLen = payLoad[mfgIndex - 1]; // length byte for this AD structure - size_t adStart = mfgIndex - 1; - size_t adEnd = adStart + adLen; // exclusive end index + Serial.println(F("[FLOCK PENGUIN BATTERY CANDIDATE]")); + Serial.print(F(" RSSI: ")); + Serial.println(rssi); + Serial.print(F(" MAC: ")); + Serial.println(mac); + Serial.print(F(" Name: ")); + Serial.println(name); + Serial.print(F(" Serial: ")); + Serial.println(serial.length() ? serial : "N/A"); - if (adEnd > len) { - adEnd = len; + Serial.print(F(" Payload: ")); + for (size_t i = 0; i < len; i++) { + Serial.printf("%02X ", payLoad[i]); + } + Serial.println(); + Serial.println(); + + #ifdef HAS_SCREEN + String display_string = ""; + display_string.concat(CYAN_KEY); + display_string.concat(String(rssi)); + display_string.concat(" "); + if (serial.length()) { + display_string.concat(serial); + display_string.concat(" "); } - size_t vendorStart = mfgIndex + 3; - if (vendorStart < adEnd) { - bool started = false; + if (name.length() == 0) { + display_string.concat(" MAC:"); + display_string.concat(mac); + } + else { + display_string.concat(" "); + display_string.concat(name); + } - for (size_t k = vendorStart; k < adEnd; k++) { - char c = (char)payLoad[k]; + uint8_t temp_len = display_string.length(); + for (uint8_t i = 0; i < 40 - temp_len; i++) { + display_string.concat(" "); + } - if (!started) { - if (c == 'T' && (k + 1) < adEnd && (char)payLoad[k + 1] == 'N') { - started = true; - serial += 'T'; - serial += 'N'; - k++; - } - } else { - // Once started, append digits (skip separators; stop on anything else) - if (c >= '0' && c <= '9') { - serial += c; - } else if (c == ' ' || c == '#' || c == '-') { - continue; - } else { + if (!display_obj.printing) { + display_obj.loading = true; + display_obj.display_buffer->add(display_string); + display_obj.loading = false; + } + #endif + + // To-do: + // track in a list like AirTag / Flipper, if you want + // (struct FlockBattery { String mac; String name; String serial; int rssi; uint32_t last_seen; }; etc.) + } + } + else if (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK_WARDRIVE) { + bool do_save = false; + #ifdef HAS_GPS + if (gps_obj.getGpsModuleStatus()) { + + unsigned char mac_char[6]; + wifi_scan_obj.copyNimbleMac(advertisedDevice->getAddress(), mac_char); + + if (wifi_scan_obj.seen_mac(mac_char)) + return; + + #ifndef HAS_DUAL_BAND + uint8_t* payLoad = advertisedDevice->getPayload(); + size_t len = advertisedDevice->getPayloadLength(); + #else + const std::vector& payLoad = advertisedDevice->getPayload(); + size_t len = payLoad.size(); + #endif + + bool hasXuntongMfg = false; + size_t mfgIndex = 0; // index of 0xFF (AD type) + + // Look for Company ID XUNTONG (0x09C8), + for (size_t i = 1; i + 3 < len; i++) { + if (payLoad[i] == 0xFF && // AD type: Manufacturer Specific + payLoad[i + 1] == 0xC8 && + payLoad[i + 2] == 0x09) { + hasXuntongMfg = true; + mfgIndex = i; + break; + } + } + + String name = advertisedDevice->getName().c_str(); + + // Check for old penguin name + bool penguin = false; + + if (name.length() > 0) { + // Old firmware: "Penguin-XXXXXXXXXX" + if (name.startsWith("Penguin-") && name.length() == 18) { + bool allDigits = true; + for (int i = 8; i < name.length(); i++) { + char c = name.charAt(i); + if (c < '0' || c > '9') { + allDigits = false; break; } } + if (allDigits) { + penguin = true; + } + } + + // Legacy name: "FS Ext Battery" + if (name == "FS Ext Battery") { + penguin = true; + } + + // New firmware: "NNNNNNNNNN" (10 digits) + if (name.length() == 10) { + bool allDigits = true; + for (int i = 0; i < name.length(); i++) { + char c = name.charAt(i); + if (c < '0' || c > '9') { + allDigits = false; + break; + } + } + if (allDigits) { + penguin = true; + } } } + + // Try to extract serial number from the XUNTONG manufacturer data + String serial = ""; + + if (hasXuntongMfg && mfgIndex > 0) { + uint8_t adLen = payLoad[mfgIndex - 1]; // length byte for this AD structure + size_t adStart = mfgIndex - 1; + size_t adEnd = adStart + adLen; // exclusive end index + + if (adEnd > len) { + adEnd = len; + } + + size_t vendorStart = mfgIndex + 3; + if (vendorStart < adEnd) { + bool started = false; + + for (size_t k = vendorStart; k < adEnd; k++) { + char c = (char)payLoad[k]; + + if (!started) { + if (c == 'T' && (k + 1) < adEnd && (char)payLoad[k + 1] == 'N') { + started = true; + serial += 'T'; + serial += 'N'; + k++; + } + } else { + // Once started, append digits (skip separators; stop on anything else) + if (c >= '0' && c <= '9') { + serial += c; + } else if (c == ' ' || c == '#' || c == '-') { + continue; + } else { + break; + } + } + } + } + } + + // Final decision on marking as Flock Penguin battery + if (hasXuntongMfg && (penguin || name.length() == 0)) { + String mac = advertisedDevice->getAddress().toString().c_str(); + mac.toUpperCase(); + int rssi = advertisedDevice->getRSSI(); + + // rssi + // mac + // name + // serial + + if (gps_obj.getFixStatus()) + do_save = true; + + #ifdef HAS_SCREEN + String display_string; + if (!do_save) + display_string = RED_KEY; + else + display_string = GREEN_KEY; + + display_string.concat(String(rssi)); + display_string.concat(" "); + if (serial.length()) { + display_string.concat(serial); + display_string.concat(" "); + } + + if (name.length() == 0) { + display_string.concat(" MAC:"); + display_string.concat(mac); + } + else { + display_string.concat(" "); + display_string.concat(name); + } + + uint8_t temp_len = display_string.length(); + for (uint8_t i = 0; i < 40 - temp_len; i++) { + display_string.concat(" "); + } + + if (!display_obj.printing) { + display_obj.loading = true; + display_obj.display_buffer->add(display_string); + display_obj.loading = false; + } + #endif + + String wardrive_line = (String)advertisedDevice->getAddress().toString().c_str() + ",,[BLE]," + gps_obj.getDatetime() + ",0," + (String)advertisedDevice->getRSSI() + "," + gps_obj.getLat() + "," + gps_obj.getLon() + "," + gps_obj.getAlt() + "," + gps_obj.getAccuracy() + ",BLE\n"; + Serial.print(wardrive_line); + + wifi_scan_obj.save_mac(mac_char); + + if (do_save) + buffer_obj.append(wardrive_line); + + // To-do: + // track in a list like AirTag / Flipper, if you want + // (struct FlockBattery { String mac; String name; String serial; int rssi; uint32_t last_seen; }; etc.) + } } + #endif + } + else if (wifi_scan_obj.currentScanMode == BT_SCAN_SIMPLE) { + wifi_scan_obj.bt_frames++; + } + else if (wifi_scan_obj.currentScanMode == BT_SCAN_SIMPLE_TWO) { + wifi_scan_obj.bt_frames++; + } + else if (wifi_scan_obj.currentScanMode == BT_SCAN_SKIMMERS) { + String bad_list[bad_list_length] = {"HC-03", "HC-05", "HC-06"}; + + #ifdef HAS_SCREEN + int buf = display_obj.display_buffer->size(); + #else + int buf = 0; + #endif + + if (buf >= 0) + { + Serial.print(F("Device: ")); + String display_string = ""; + if(advertisedDevice->getName().length() != 0) + { + Serial.print(advertisedDevice->getName().c_str()); + for(uint8_t i = 0; i < bad_list_length; i++) + { + #ifdef HAS_SCREEN + if(strcmp(advertisedDevice->getName().c_str(), bad_list[i].c_str()) == 0) + { + display_string.concat(text_table4[1]); + display_string.concat(" "); + display_string.concat(advertisedDevice->getName().c_str()); + uint8_t temp_len = display_string.length(); + for (uint8_t i = 0; i < 40 - temp_len; i++) + { + display_string.concat(" "); + } + while (display_obj.printing) + delay(1); + display_obj.loading = true; + display_obj.display_buffer->add(display_string); + display_obj.loading = false; + } + #endif + } + } + else + { + Serial.print(advertisedDevice->getAddress().toString().c_str()); + } + Serial.print(F(" RSSI: ")); + Serial.println(advertisedDevice->getRSSI()); + } + } - // Final decision on marking as Flock Penguin battery - if (hasXuntongMfg && (penguin || name.length() == 0)) { - String mac = advertisedDevice->getAddress().toString().c_str(); - mac.toUpperCase(); - int rssi = advertisedDevice->getRSSI(); - - // rssi - // mac - // name - // serial - - if (gps_obj.getFixStatus()) - do_save = true; - + return; + } + }; + + /*class bluetoothScanSkimmersCallback: public BLEAdvertisedDeviceCallbacks { + void onResult(BLEAdvertisedDevice *advertisedDevice) { + String bad_list[bad_list_length] = {"HC-03", "HC-05", "HC-06"}; + + #ifdef HAS_SCREEN + int buf = display_obj.display_buffer->size(); + #else + int buf = 0; + #endif + + if (buf >= 0) + { + Serial.print(F("Device: ")); + String display_string = ""; + if(advertisedDevice->getName().length() != 0) + { + Serial.print(advertisedDevice->getName().c_str()); + for(uint8_t i = 0; i < bad_list_length; i++) + { #ifdef HAS_SCREEN - String display_string; - if (!do_save) - display_string = RED_KEY; - else - display_string = GREEN_KEY; - - display_string.concat(String(rssi)); - display_string.concat(" "); - if (serial.length()) { - display_string.concat(serial); + if(strcmp(advertisedDevice->getName().c_str(), bad_list[i].c_str()) == 0) + { + display_string.concat(text_table4[1]); display_string.concat(" "); - } - - if (name.length() == 0) { - display_string.concat(" MAC:"); - display_string.concat(mac); - } - else { - display_string.concat(" "); - display_string.concat(name); - } - - uint8_t temp_len = display_string.length(); - for (uint8_t i = 0; i < 40 - temp_len; i++) { - display_string.concat(" "); - } - - if (!display_obj.printing) { + display_string.concat(advertisedDevice->getName().c_str()); + uint8_t temp_len = display_string.length(); + for (uint8_t i = 0; i < 40 - temp_len; i++) + { + display_string.concat(" "); + } + while (display_obj.printing) + delay(1); display_obj.loading = true; display_obj.display_buffer->add(display_string); display_obj.loading = false; } #endif - - String wardrive_line = (String)advertisedDevice->getAddress().toString().c_str() + ",,[BLE]," + gps_obj.getDatetime() + ",0," + (String)advertisedDevice->getRSSI() + "," + gps_obj.getLat() + "," + gps_obj.getLon() + "," + gps_obj.getAlt() + "," + gps_obj.getAccuracy() + ",BLE\n"; - Serial.print(wardrive_line); - - wifi_scan_obj.save_mac(mac_char); - - if (do_save) - buffer_obj.append(wardrive_line); - - // To-do: - // track in a list like AirTag / Flipper, if you want - // (struct FlockBattery { String mac; String name; String serial; int rssi; uint32_t last_seen; }; etc.) } } - #endif - } - else if (wifi_scan_obj.currentScanMode == BT_SCAN_SIMPLE) { - wifi_scan_obj.bt_frames++; - } - else if (wifi_scan_obj.currentScanMode == BT_SCAN_SIMPLE_TWO) { - wifi_scan_obj.bt_frames++; - } - - return; - } - }; - - class bluetoothScanSkimmersCallback: public BLEAdvertisedDeviceCallbacks { - void onResult(BLEAdvertisedDevice *advertisedDevice) { - String bad_list[bad_list_length] = {"HC-03", "HC-05", "HC-06"}; - - #ifdef HAS_SCREEN - int buf = display_obj.display_buffer->size(); - #else - int buf = 0; - #endif - - if (buf >= 0) - { - Serial.print("Device: "); - String display_string = ""; - if(advertisedDevice->getName().length() != 0) - { - Serial.print(advertisedDevice->getName().c_str()); - for(uint8_t i = 0; i < bad_list_length; i++) + else { - #ifdef HAS_SCREEN - if(strcmp(advertisedDevice->getName().c_str(), bad_list[i].c_str()) == 0) - { - display_string.concat(text_table4[1]); - display_string.concat(" "); - display_string.concat(advertisedDevice->getName().c_str()); + Serial.print(advertisedDevice->getAddress().toString().c_str()); + } + Serial.print(F(" RSSI: ")); + Serial.println(advertisedDevice->getRSSI()); + } + } + };*/ + #else + class bluetoothScanAllCallback: public NimBLEScanCallbacks { + + void onResult(const NimBLEAdvertisedDevice* advertisedDevice) override { + + extern WiFiScan wifi_scan_obj; + + //#ifdef HAS_SCREEN + // int buf = display_obj.display_buffer->size(); + //#else + int buf = 0; + //#endif + + String display_string = ""; + + if ((wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG) || + (wifi_scan_obj.currentScanMode == BT_SCAN_AIRTAG_MON)) { + #ifndef HAS_DUAL_BAND + uint8_t* payLoad = advertisedDevice->getPayload(); + size_t len = advertisedDevice->getPayloadLength(); + #else + const std::vector& payLoad = advertisedDevice->getPayload(); + size_t len = payLoad.size(); + #endif + + bool match = false; + for (int i = 0; i <= len - 4; i++) { + if (payLoad[i] == 0x1E && payLoad[i+1] == 0xFF && payLoad[i+2] == 0x4C && payLoad[i+3] == 0x00) { + match = true; + break; + } + if (payLoad[i] == 0x4C && payLoad[i+1] == 0x00 && payLoad[i+2] == 0x12 && payLoad[i+3] == 0x19) { + match = true; + break; + } + } + + int rssi = advertisedDevice->getRSSI(); + + if (match) { + String mac = advertisedDevice->getAddress().toString().c_str(); + mac.toUpperCase(); + + for (int i = 0; i < airtags->size(); i++) { + // Airtag is in list already. Update RSSI + if (mac == airtags->get(i).mac) { + AirTag old_airtag = airtags->get(i); + old_airtag.rssi = rssi; + old_airtag.last_seen = millis(); + airtags->set(i, old_airtag); + return; + } + } + + Serial.print(F("RSSI: ")); + Serial.print(rssi); + Serial.print(F(" MAC: ")); + Serial.println(mac); + Serial.print(F("Len: ")); + Serial.print(len); + Serial.print(F(" Payload: ")); + for (size_t i = 0; i < len; i++) { + Serial.printf("%02X ", payLoad[i]); + } + Serial.println("\n"); + + AirTag airtag; + airtag.mac = mac; + #ifndef HAS_DUAL_BAND + airtag.payload.assign(payLoad, payLoad + len); + airtag.payloadSize = len; + #else + airtag.payload = payLoad; + airtag.payloadSize = payLoad.size(); + #endif + airtag.rssi = rssi; + airtag.last_seen = millis(); + + airtags->add(airtag); + + + if (wifi_scan_obj.currentScanMode != BT_SCAN_AIRTAG_MON) { + #ifdef HAS_SCREEN + //display_string.concat("RSSI: "); + display_string.concat((String)rssi); + display_string.concat(" MAC: "); + display_string.concat(mac); uint8_t temp_len = display_string.length(); for (uint8_t i = 0; i < 40 - temp_len; i++) { display_string.concat(" "); } - while (display_obj.printing) - delay(1); + display_obj.display_buffer->add(display_string); + #endif + } + } + } + else if (wifi_scan_obj.currentScanMode == BT_SCAN_FLIPPER) { + #ifndef HAS_DUAL_BAND + uint8_t* payLoad = advertisedDevice->getPayload(); + size_t len = advertisedDevice->getPayloadLength(); + #else + const std::vector& payLoad = advertisedDevice->getPayload(); + size_t len = payLoad.size(); + #endif + + bool match = false; + String color = ""; + for (int i = 0; i <= len - 4; i++) { + if (payLoad[i] == 0x81 && payLoad[i+1] == 0x30) { + match = true; + color = "Black"; + break; + } + if (payLoad[i] == 0x82 && payLoad[i+1] == 0x30) { + match = true; + color = "White"; + break; + } + if (payLoad[i] == 0x83 && payLoad[i+1] == 0x30) { + color = "Transparent"; + match = true; + break; + } + } + + if (match) { + String mac = advertisedDevice->getAddress().toString().c_str(); + String name = advertisedDevice->getName().c_str(); + mac.toUpperCase(); + + for (int i = 0; i < flippers->size(); i++) { + if (mac == flippers->get(i).mac) + return; + } + + int rssi = advertisedDevice->getRSSI(); + Serial.print(F("RSSI: ")); + Serial.print(rssi); + Serial.print(F(" MAC: ")); + Serial.println(mac); + Serial.print(F("Name: ")); + Serial.println(name); + + Flipper flipper; + flipper.mac = mac; + flipper.name = name; + + flippers->add(flipper); + + #ifdef HAS_SCREEN + display_obj.display_buffer->add(String("Flipper: ") + name + ", "); + display_obj.display_buffer->add(" MAC: " + String(mac) + ", "); + display_obj.display_buffer->add(" RSSI: " + String(rssi) + ", "); + display_obj.display_buffer->add(" Color: " + String(color) + " "); + #endif + } + } + else if (wifi_scan_obj.currentScanMode == BT_SCAN_ALL) { + if (buf >= 0) + { + display_string.concat(text_table4[0]); + display_string.concat(advertisedDevice->getRSSI()); + Serial.print(F(" RSSI: ")); + Serial.print(advertisedDevice->getRSSI()); + + display_string.concat(" "); + Serial.print(" "); + + Serial.print(F("Device: ")); + if(advertisedDevice->getName().length() != 0) + { + 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()); + } + + #ifdef HAS_SCREEN + uint8_t temp_len = display_string.length(); + for (uint8_t i = 0; i < 40 - temp_len; i++) + { + display_string.concat(" "); + } + + Serial.println(); + + while (display_obj.printing) + delay(1); + display_obj.loading = true; + display_obj.display_buffer->add(display_string); + display_obj.loading = false; + #endif + } + } + else if ((wifi_scan_obj.currentScanMode == BT_SCAN_WAR_DRIVE) || (wifi_scan_obj.currentScanMode == BT_SCAN_WAR_DRIVE_CONT)) { + #ifdef HAS_GPS + if (gps_obj.getGpsModuleStatus()) { + bool do_save = false; + if (buf >= 0) + { + Serial.print(F("Device: ")); + if(advertisedDevice->getName().length() != 0) + { + 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()); + } + + if (gps_obj.getFixStatus()) { + do_save = true; + display_string.concat(" | Lt: " + gps_obj.getLat()); + display_string.concat(" | Ln: " + gps_obj.getLon()); + } + else { + display_string.concat(" | GPS: No Fix"); + } + + #ifdef HAS_SCREEN + uint8_t temp_len = display_string.length(); + for (uint8_t i = 0; i < 40 - temp_len; i++) + { + display_string.concat(" "); + } + + Serial.println(); + + while (display_obj.printing) + delay(1); + display_obj.loading = true; + display_obj.display_buffer->add(display_string); + display_obj.loading = false; + #endif + + String wardrive_line = (String)advertisedDevice->getAddress().toString().c_str() + ",,[BLE]," + gps_obj.getDatetime() + ",0," + (String)advertisedDevice->getRSSI() + "," + gps_obj.getLat() + "," + gps_obj.getLon() + "," + gps_obj.getAlt() + "," + gps_obj.getAccuracy() + ",BLE\n"; + Serial.print(wardrive_line); + + if (do_save) + buffer_obj.append(wardrive_line); + } + } + #endif + } + else if (wifi_scan_obj.currentScanMode == BT_SCAN_ANALYZER) { + wifi_scan_obj._analyzer_value++; + + if (wifi_scan_obj.analyzer_frames_recvd < 254) + wifi_scan_obj.analyzer_frames_recvd++; + + if (wifi_scan_obj.analyzer_frames_recvd > ANALYZER_NAME_REFRESH) { + display_string.concat(advertisedDevice->getRSSI()); + display_string.concat(" "); + + if(advertisedDevice->getName().length() != 0) + display_string.concat(advertisedDevice->getName().c_str()); + else + display_string.concat(advertisedDevice->getAddress().toString().c_str()); + + wifi_scan_obj.analyzer_frames_recvd = 0; + wifi_scan_obj.analyzer_name_string = display_string; + wifi_scan_obj.analyzer_name_update = true; + } + } + else if (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) { + #ifndef HAS_DUAL_BAND + uint8_t* payLoad = advertisedDevice->getPayload(); + size_t len = advertisedDevice->getPayloadLength(); + #else + const std::vector& payLoad = advertisedDevice->getPayload(); + size_t len = payLoad.size(); + #endif + + bool hasXuntongMfg = false; + size_t mfgIndex = 0; // index of 0xFF (AD type) + + // Look for Company ID XUNTONG (0x09C8), + for (size_t i = 1; i + 3 < len; i++) { + if (payLoad[i] == 0xFF && // AD type: Manufacturer Specific + payLoad[i + 1] == 0xC8 && + payLoad[i + 2] == 0x09) { + hasXuntongMfg = true; + mfgIndex = i; + break; + } + } + + String name = advertisedDevice->getName().c_str(); + + // Check for old penguin name + bool penguin = false; + + if (name.length() > 0) { + // Old firmware: "Penguin-XXXXXXXXXX" + if (name.startsWith("Penguin-") && name.length() == 18) { + bool allDigits = true; + for (int i = 8; i < name.length(); i++) { + char c = name.charAt(i); + if (c < '0' || c > '9') { + allDigits = false; + break; + } + } + if (allDigits) { + penguin = true; + } + } + + // Legacy name: "FS Ext Battery" + if (name == "FS Ext Battery") { + penguin = true; + } + + // New firmware: "NNNNNNNNNN" (10 digits) + if (name.length() == 10) { + bool allDigits = true; + for (int i = 0; i < name.length(); i++) { + char c = name.charAt(i); + if (c < '0' || c > '9') { + allDigits = false; + break; + } + } + if (allDigits) { + penguin = true; + } + } + } + + // Try to extract serial number from the XUNTONG manufacturer data + String serial = ""; + + if (hasXuntongMfg && mfgIndex > 0) { + uint8_t adLen = payLoad[mfgIndex - 1]; // length byte for this AD structure + size_t adStart = mfgIndex - 1; + size_t adEnd = adStart + adLen; // exclusive end index + + if (adEnd > len) { + adEnd = len; + } + + size_t vendorStart = mfgIndex + 3; + if (vendorStart < adEnd) { + bool started = false; + + for (size_t k = vendorStart; k < adEnd; k++) { + char c = (char)payLoad[k]; + + if (!started) { + if (c == 'T' && (k + 1) < adEnd && (char)payLoad[k + 1] == 'N') { + started = true; + serial += 'T'; + serial += 'N'; + k++; + } + } else { + // Once started, append digits (skip separators; stop on anything else) + if (c >= '0' && c <= '9') { + serial += c; + } else if (c == ' ' || c == '#' || c == '-') { + continue; + } else { + break; + } + } + } + } + } + + // Final decision on marking as Flock Penguin battery + if (hasXuntongMfg && (penguin || name.length() == 0)) { + String mac = advertisedDevice->getAddress().toString().c_str(); + mac.toUpperCase(); + int rssi = advertisedDevice->getRSSI(); + + Serial.println(F("[FLOCK PENGUIN BATTERY CANDIDATE]")); + Serial.print(F(" RSSI: ")); + Serial.println(rssi); + Serial.print(F(" MAC: ")); + Serial.println(mac); + Serial.print(F(" Name: ")); + Serial.println(name); + Serial.print(F(" Serial: ")); + Serial.println(serial.length() ? serial : "N/A"); + + Serial.print(F(" Payload: ")); + for (size_t i = 0; i < len; i++) { + Serial.printf("%02X ", payLoad[i]); + } + Serial.println(); + Serial.println(); + + #ifdef HAS_SCREEN + String display_string = ""; + display_string.concat(CYAN_KEY); + display_string.concat(String(rssi)); + display_string.concat(" "); + if (serial.length()) { + display_string.concat(serial); + display_string.concat(" "); + } + + if (name.length() == 0) { + display_string.concat(" MAC:"); + display_string.concat(mac); + } + else { + display_string.concat(" "); + display_string.concat(name); + } + + uint8_t temp_len = display_string.length(); + for (uint8_t i = 0; i < 40 - temp_len; i++) { + display_string.concat(" "); + } + + if (!display_obj.printing) { display_obj.loading = true; display_obj.display_buffer->add(display_string); display_obj.loading = false; } #endif + + // To-do: + // track in a list like AirTag / Flipper, if you want + // (struct FlockBattery { String mac; String name; String serial; int rssi; uint32_t last_seen; }; etc.) } } - else - { - Serial.print(advertisedDevice->getAddress().toString().c_str()); + else if (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK_WARDRIVE) { + bool do_save = false; + #ifdef HAS_GPS + if (gps_obj.getGpsModuleStatus()) { + + unsigned char mac_char[6]; + wifi_scan_obj.copyNimbleMac(advertisedDevice->getAddress(), mac_char); + + if (wifi_scan_obj.seen_mac(mac_char)) + return; + + #ifndef HAS_DUAL_BAND + uint8_t* payLoad = advertisedDevice->getPayload(); + size_t len = advertisedDevice->getPayloadLength(); + #else + const std::vector& payLoad = advertisedDevice->getPayload(); + size_t len = payLoad.size(); + #endif + + bool hasXuntongMfg = false; + size_t mfgIndex = 0; // index of 0xFF (AD type) + + // Look for Company ID XUNTONG (0x09C8), + for (size_t i = 1; i + 3 < len; i++) { + if (payLoad[i] == 0xFF && // AD type: Manufacturer Specific + payLoad[i + 1] == 0xC8 && + payLoad[i + 2] == 0x09) { + hasXuntongMfg = true; + mfgIndex = i; + break; + } + } + + String name = advertisedDevice->getName().c_str(); + + // Check for old penguin name + bool penguin = false; + + if (name.length() > 0) { + // Old firmware: "Penguin-XXXXXXXXXX" + if (name.startsWith("Penguin-") && name.length() == 18) { + bool allDigits = true; + for (int i = 8; i < name.length(); i++) { + char c = name.charAt(i); + if (c < '0' || c > '9') { + allDigits = false; + break; + } + } + if (allDigits) { + penguin = true; + } + } + + // Legacy name: "FS Ext Battery" + if (name == "FS Ext Battery") { + penguin = true; + } + + // New firmware: "NNNNNNNNNN" (10 digits) + if (name.length() == 10) { + bool allDigits = true; + for (int i = 0; i < name.length(); i++) { + char c = name.charAt(i); + if (c < '0' || c > '9') { + allDigits = false; + break; + } + } + if (allDigits) { + penguin = true; + } + } + } + + // Try to extract serial number from the XUNTONG manufacturer data + String serial = ""; + + if (hasXuntongMfg && mfgIndex > 0) { + uint8_t adLen = payLoad[mfgIndex - 1]; // length byte for this AD structure + size_t adStart = mfgIndex - 1; + size_t adEnd = adStart + adLen; // exclusive end index + + if (adEnd > len) { + adEnd = len; + } + + size_t vendorStart = mfgIndex + 3; + if (vendorStart < adEnd) { + bool started = false; + + for (size_t k = vendorStart; k < adEnd; k++) { + char c = (char)payLoad[k]; + + if (!started) { + if (c == 'T' && (k + 1) < adEnd && (char)payLoad[k + 1] == 'N') { + started = true; + serial += 'T'; + serial += 'N'; + k++; + } + } else { + // Once started, append digits (skip separators; stop on anything else) + if (c >= '0' && c <= '9') { + serial += c; + } else if (c == ' ' || c == '#' || c == '-') { + continue; + } else { + break; + } + } + } + } + } + + // Final decision on marking as Flock Penguin battery + if (hasXuntongMfg && (penguin || name.length() == 0)) { + String mac = advertisedDevice->getAddress().toString().c_str(); + mac.toUpperCase(); + int rssi = advertisedDevice->getRSSI(); + + // rssi + // mac + // name + // serial + + if (gps_obj.getFixStatus()) + do_save = true; + + #ifdef HAS_SCREEN + String display_string; + if (!do_save) + display_string = RED_KEY; + else + display_string = GREEN_KEY; + + display_string.concat(String(rssi)); + display_string.concat(" "); + if (serial.length()) { + display_string.concat(serial); + display_string.concat(" "); + } + + if (name.length() == 0) { + display_string.concat(" MAC:"); + display_string.concat(mac); + } + else { + display_string.concat(" "); + display_string.concat(name); + } + + uint8_t temp_len = display_string.length(); + for (uint8_t i = 0; i < 40 - temp_len; i++) { + display_string.concat(" "); + } + + if (!display_obj.printing) { + display_obj.loading = true; + display_obj.display_buffer->add(display_string); + display_obj.loading = false; + } + #endif + + String wardrive_line = (String)advertisedDevice->getAddress().toString().c_str() + ",,[BLE]," + gps_obj.getDatetime() + ",0," + (String)advertisedDevice->getRSSI() + "," + gps_obj.getLat() + "," + gps_obj.getLon() + "," + gps_obj.getAlt() + "," + gps_obj.getAccuracy() + ",BLE\n"; + Serial.print(wardrive_line); + + wifi_scan_obj.save_mac(mac_char); + + if (do_save) + buffer_obj.append(wardrive_line); + + // To-do: + // track in a list like AirTag / Flipper, if you want + // (struct FlockBattery { String mac; String name; String serial; int rssi; uint32_t last_seen; }; etc.) + } + } + #endif } - Serial.print(" RSSI: "); - Serial.println(advertisedDevice->getRSSI()); + else if (wifi_scan_obj.currentScanMode == BT_SCAN_SIMPLE) { + wifi_scan_obj.bt_frames++; + } + else if (wifi_scan_obj.currentScanMode == BT_SCAN_SIMPLE_TWO) { + wifi_scan_obj.bt_frames++; + } + else if (wifi_scan_obj.currentScanMode == BT_SCAN_SKIMMERS) { + String bad_list[bad_list_length] = {"HC-03", "HC-05", "HC-06"}; + + #ifdef HAS_SCREEN + int buf = display_obj.display_buffer->size(); + #else + int buf = 0; + #endif + + if (buf >= 0) + { + Serial.print(F("Device: ")); + String display_string = ""; + if(advertisedDevice->getName().length() != 0) + { + Serial.print(advertisedDevice->getName().c_str()); + for(uint8_t i = 0; i < bad_list_length; i++) + { + #ifdef HAS_SCREEN + if(strcmp(advertisedDevice->getName().c_str(), bad_list[i].c_str()) == 0) + { + display_string.concat(text_table4[1]); + display_string.concat(" "); + display_string.concat(advertisedDevice->getName().c_str()); + uint8_t temp_len = display_string.length(); + for (uint8_t i = 0; i < 40 - temp_len; i++) + { + display_string.concat(" "); + } + while (display_obj.printing) + delay(1); + display_obj.loading = true; + display_obj.display_buffer->add(display_string); + display_obj.loading = false; + } + #endif + } + } + else + { + Serial.print(advertisedDevice->getAddress().toString().c_str()); + } + Serial.print(F(" RSSI: ")); + Serial.println(advertisedDevice->getRSSI()); + } + } + return; } - } - }; + }; + + /*class bluetoothScanSkimmersCallback: public NimBLEScanCallbacks { + void onResult(const NimBLEAdvertisedDevice* advertisedDevice) override { + String bad_list[bad_list_length] = {"HC-03", "HC-05", "HC-06"}; + + #ifdef HAS_SCREEN + int buf = display_obj.display_buffer->size(); + #else + int buf = 0; + #endif + + if (buf >= 0) + { + Serial.print(F("Device: ")); + String display_string = ""; + if(advertisedDevice->getName().length() != 0) + { + Serial.print(advertisedDevice->getName().c_str()); + for(uint8_t i = 0; i < bad_list_length; i++) + { + #ifdef HAS_SCREEN + if(strcmp(advertisedDevice->getName().c_str(), bad_list[i].c_str()) == 0) + { + display_string.concat(text_table4[1]); + display_string.concat(" "); + display_string.concat(advertisedDevice->getName().c_str()); + uint8_t temp_len = display_string.length(); + for (uint8_t i = 0; i < 40 - temp_len; i++) + { + display_string.concat(" "); + } + while (display_obj.printing) + delay(1); + display_obj.loading = true; + display_obj.display_buffer->add(display_string); + display_obj.loading = false; + } + #endif + } + } + else + { + Serial.print(advertisedDevice->getAddress().toString().c_str()); + } + Serial.print(F(" RSSI: ")); + Serial.println(advertisedDevice->getRSSI()); + } + } + };*/ + #endif #endif @@ -1043,37 +1855,38 @@ int WiFiScan::generateSSIDs(int count) { Serial.println(ssids->get(ssids->size() - 1).essid); } - Serial.print("Free Heap: "); - Serial.print(esp_get_free_heap_size()); - #ifdef HAS_PSRAM - Serial.print(" Free PSRAM: "); - Serial.println(heap_caps_get_free_size(MALLOC_CAP_SPIRAM)); - #endif - return num_gen; } +void WiFiScan::setNetworkInfo() { + this->ip_addr = WiFi.localIP(); + this->gateway = WiFi.gatewayIP(); + this->subnet = WiFi.subnetMask(); +} + +void WiFiScan::showNetworkInfo() { + Serial.print(F("IP address: ")); + Serial.println(this->ip_addr); + Serial.print(F("Gateway: ")); + Serial.println(this->gateway); + Serial.print(F("Netmask: ")); + Serial.println(this->subnet); + Serial.print(F("MAC: ")); + Serial.println(WiFi.macAddress()); +} + bool WiFiScan::joinWiFi(String ssid, String password, bool gui) { static const char * btns[] ={text16, ""}; int count = 0; if ((WiFi.status() == WL_CONNECTED) && (ssid == connected_network) && (ssid != "")) { - #ifdef HAS_TOUCH - if (gui) { - lv_obj_t * mbox1 = lv_msgbox_create(lv_scr_act(), NULL); - lv_msgbox_set_text(mbox1, text_table4[2]); - lv_msgbox_add_btns(mbox1, btns); - lv_obj_set_width(mbox1, 200); - lv_obj_align(mbox1, NULL, LV_ALIGN_CENTER, 0, 0); //Align to the corner - } - #endif this->wifi_initialized = true; this->currentScanMode = WIFI_CONNECTED; return true; } else if (WiFi.status() == WL_CONNECTED) { - Serial.println("Already connected. Disconnecting..."); + Serial.println(F("Already connected. Disconnecting...")); WiFi.disconnect(); } @@ -1088,48 +1901,32 @@ bool WiFiScan::joinWiFi(String ssid, String password, bool gui) WiFi.begin(ssid.c_str(), password.c_str()); #ifdef HAS_SCREEN - #ifdef HAS_MINI_KB - if (gui) { - display_obj.clearScreen(); - display_obj.tft.setCursor(0, TFT_HEIGHT / 2); - display_obj.tft.setTextSize(1); - display_obj.tft.print("Connecting"); - display_obj.tft.setTextWrap(true, false); - } - #endif + if (gui) { + display_obj.clearScreen(); + display_obj.tft.setCursor(0, TFT_HEIGHT / 2); + display_obj.tft.setTextSize(1); + display_obj.tft.print("Connecting"); + display_obj.tft.setTextWrap(true, false); + } #endif - Serial.print("Connecting to WiFi"); + Serial.print(F("Connecting to WiFi")); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); #ifdef HAS_SCREEN - #ifdef HAS_MINI_KB - if (gui) { - display_obj.tft.print("."); - } - #endif + if (gui) { + display_obj.tft.print("."); + } #endif count++; if (count == 20) { - Serial.println("\nCould not connect to WiFi network"); + Serial.println(F("\nCould not connect to WiFi network")); #ifdef HAS_SCREEN - #ifdef HAS_MINI_KB - if (gui) { - display_obj.tft.println("\nFailed to connect"); - delay(1000); - } - #endif - #endif - #ifdef HAS_TOUCH if (gui) { - lv_obj_t * mbox1 = lv_msgbox_create(lv_scr_act(), NULL); - lv_msgbox_set_text(mbox1, text_table4[3]); - lv_msgbox_add_btns(mbox1, btns); - lv_obj_set_width(mbox1, 200); - //lv_obj_set_event_cb(mbox1, event_handler); - lv_obj_align(mbox1, NULL, LV_ALIGN_CENTER, 0, 0); //Align to the corner + display_obj.tft.println("\nFailed to connect"); + delay(1000); } #endif this->wifi_initialized = true; @@ -1140,43 +1937,22 @@ bool WiFiScan::joinWiFi(String ssid, String password, bool gui) return false; } } - - #ifdef HAS_TOUCH - lv_obj_t * mbox1 = lv_msgbox_create(lv_scr_act(), NULL); - lv_msgbox_set_text(mbox1, text_table4[4]); - lv_msgbox_add_btns(mbox1, btns); - lv_obj_set_width(mbox1, 200); - lv_obj_align(mbox1, NULL, LV_ALIGN_CENTER, 0, 0); //Align to the corner - #endif this->connected_network = ssid; - this->ip_addr = WiFi.localIP(); - this->gateway = WiFi.gatewayIP(); - this->subnet = WiFi.subnetMask(); - - Serial.println("\nConnected to the WiFi network"); - Serial.print("IP address: "); - Serial.println(this->ip_addr); - Serial.print("Gateway: "); - Serial.println(this->gateway); - Serial.print("Netmask: "); - Serial.println(this->subnet); - Serial.print("MAC: "); - Serial.println(WiFi.macAddress()); + this->setNetworkInfo(); + this->showNetworkInfo(); #ifdef HAS_SCREEN - #ifdef HAS_MINI_KB - display_obj.tft.println("\nConnected!"); - display_obj.tft.print("IP address: "); - display_obj.tft.println(this->ip_addr); - display_obj.tft.print("Gateway: "); - display_obj.tft.println(this->gateway); - display_obj.tft.print("Netmask: "); - display_obj.tft.println(this->subnet); - display_obj.tft.print("MAC: "); - display_obj.tft.println(WiFi.macAddress()); - display_obj.tft.println("Returning..."); - delay(2000); - #endif + display_obj.tft.println("\nConnected!"); + display_obj.tft.print("IP address: "); + display_obj.tft.println(this->ip_addr); + display_obj.tft.print("Gateway: "); + display_obj.tft.println(this->gateway); + display_obj.tft.print("Netmask: "); + display_obj.tft.println(this->subnet); + display_obj.tft.print("MAC: "); + display_obj.tft.println(WiFi.macAddress()); + display_obj.tft.println("Returning..."); + delay(2000); #endif this->wifi_initialized = true; #ifndef HAS_TOUCH @@ -1198,21 +1974,12 @@ bool WiFiScan::startWiFi(String ssid, String password, bool gui) int count = 0; if ((WiFi.status() == WL_CONNECTED) && (ssid == connected_network) && (ssid != "")) { - #ifdef HAS_TOUCH - if (gui) { - lv_obj_t * mbox1 = lv_msgbox_create(lv_scr_act(), NULL); - lv_msgbox_set_text(mbox1, text_table4[2]); - lv_msgbox_add_btns(mbox1, btns); - lv_obj_set_width(mbox1, 200); - lv_obj_align(mbox1, NULL, LV_ALIGN_CENTER, 0, 0); //Align to the corner - } - #endif this->wifi_initialized = true; this->currentScanMode = WIFI_CONNECTED; return true; } else if (WiFi.status() == WL_CONNECTED) { - Serial.println("Already connected. Disconnecting..."); + Serial.println(F("Already connected. Disconnecting...")); WiFi.disconnect(); } @@ -1220,7 +1987,6 @@ bool WiFiScan::startWiFi(String ssid, String password, bool gui) delay(100); WiFi.mode(WIFI_MODE_AP); - //esp_wifi_set_mode(WIFI_IF_STA); this->setMac(); @@ -1230,67 +1996,41 @@ bool WiFiScan::startWiFi(String ssid, String password, bool gui) WiFi.softAP(ssid.c_str()); #ifdef HAS_SCREEN - #ifdef HAS_MINI_KB - if (gui) { - display_obj.clearScreen(); - display_obj.tft.setCursor(0, TFT_HEIGHT / 2); - display_obj.tft.setTextSize(1); - display_obj.tft.print("Starting"); - display_obj.tft.setTextWrap(true, false); - } - #endif + if (gui) { + display_obj.clearScreen(); + display_obj.tft.setCursor(0, TFT_HEIGHT / 2); + display_obj.tft.setTextSize(1); + display_obj.tft.print("Starting"); + display_obj.tft.setTextWrap(true, false); + } #endif - Serial.print("Started WiFi"); + Serial.print(F("Started WiFi")); - #ifdef HAS_TOUCH - lv_obj_t * mbox1 = lv_msgbox_create(lv_scr_act(), NULL); - lv_msgbox_set_text(mbox1, text_table4[4]); - lv_msgbox_add_btns(mbox1, btns); - lv_obj_set_width(mbox1, 200); - lv_obj_align(mbox1, NULL, LV_ALIGN_CENTER, 0, 0); //Align to the corner - #endif this->connected_network = ssid; - this->ip_addr = WiFi.softAPIP(); - this->gateway = WiFi.gatewayIP(); - this->subnet = WiFi.subnetMask(); + this->setNetworkInfo(); - Serial.println("\nStarted AP"); - Serial.print("IP address: "); - Serial.println(this->ip_addr); - Serial.print("Gateway: "); - Serial.println(this->gateway); - Serial.print("Netmask: "); - Serial.println(this->subnet); - Serial.print("MAC: "); - Serial.println(WiFi.macAddress()); + this->showNetworkInfo(); #ifdef HAS_SCREEN - #ifdef HAS_MINI_KB - display_obj.tft.println("\nStarted AP"); - display_obj.tft.print("IP address: "); - display_obj.tft.println(this->ip_addr); - display_obj.tft.print("Gateway: "); - display_obj.tft.println(this->gateway); - display_obj.tft.print("Netmask: "); - display_obj.tft.println(this->subnet); - display_obj.tft.print("MAC: "); - display_obj.tft.println(WiFi.macAddress()); - display_obj.tft.println("Returning..."); - delay(2000); - #endif + display_obj.tft.println(F("\nStarted AP")); + display_obj.tft.print(F("IP address: ")); + display_obj.tft.println(this->ip_addr); + display_obj.tft.print(F("Gateway: ")); + display_obj.tft.println(this->gateway); + display_obj.tft.print(F("Netmask: ")); + display_obj.tft.println(this->subnet); + display_obj.tft.print(F("MAC: ")); + display_obj.tft.println(WiFi.macAddress()); + display_obj.tft.println(F("Returning...")); + delay(2000); #endif this->wifi_initialized = true; - #ifndef HAS_TOUCH - this->currentScanMode = WIFI_CONNECTED; - #ifdef HAS_SCREEN - display_obj.tft.setTextWrap(false, false); - #endif + this->currentScanMode = WIFI_CONNECTED; + #ifdef HAS_SCREEN + display_obj.tft.setTextWrap(false, false); #endif - //settings_obj.saveSetting("APSSID", ssid); - //settings_obj.saveSetting("APPW", password); - return true; } @@ -1407,6 +2147,9 @@ void WiFiScan::StartScan(uint8_t scan_mode, uint16_t color) (scan_mode == BT_SCAN_ANALYZER) || (scan_mode == BT_SCAN_SIMPLE) || (scan_mode == BT_SCAN_SIMPLE_TWO)) { + if (scan_mode == BT_SCAN_FLOCK) + this->RunProbeScan(scan_mode, color); + #ifdef HAS_BT RunBluetoothScan(scan_mode, color); #endif @@ -1437,16 +2180,6 @@ void WiFiScan::StartScan(uint8_t scan_mode, uint16_t color) RunBluetoothScan(scan_mode, color); #endif } - else if (scan_mode == LV_ADD_SSID) { - #ifdef HAS_SCREEN - RunLvJoinWiFi(scan_mode, color); - #endif - } - else if (scan_mode == LV_JOIN_WIFI) { - #ifdef HAS_SCREEN - RunLvJoinWiFi(scan_mode, color); - #endif - } else if (scan_mode == WIFI_SCAN_GPS_NMEA){ #ifdef HAS_GPS gps_obj.enable_queue(); @@ -1584,12 +2317,15 @@ bool WiFiScan::shutdownWiFi() { bool WiFiScan::shutdownBLE() { #ifdef HAS_BT if (this->ble_initialized) { - Serial.println("Shutting down BLE"); + Serial.println(F("Shutting down BLE")); pAdvertising->stop(); pBLEScan->stop(); pBLEScan->clearResults(); - NimBLEDevice::deinit(); + + #ifndef HAS_DUAL_BAND + NimBLEDevice::deinit(); + #endif this->_analyzer_value = 0; this->bt_frames = 0; @@ -1683,6 +2419,8 @@ void WiFiScan::StopScan(uint8_t scan_mode) (currentScanMode == WIFI_SCAN_CHAN_ACT) || (currentScanMode == WIFI_SCAN_PACKET_RATE) || (currentScanMode == WIFI_CONNECTED) || + (currentScanMode == BT_SCAN_FLOCK) || + (currentScanMode == BT_SCAN_FLOCK_WARDRIVE) || (currentScanMode == LV_JOIN_WIFI) || (this->wifi_initialized)) { @@ -1716,13 +2454,13 @@ void WiFiScan::StopScan(uint8_t scan_mode) evil_portal_obj.has_ap = false; } - else if ((currentScanMode == GPS_TRACKER) || + if ((currentScanMode == GPS_TRACKER) || (currentScanMode == GPS_POI)) { this->writeFooter(currentScanMode == GPS_POI); } - else if ((currentScanMode == BT_SCAN_ALL) || + if ((currentScanMode == BT_SCAN_ALL) || (currentScanMode == BT_SCAN_AIRTAG) || (currentScanMode == BT_SCAN_AIRTAG_MON) || (currentScanMode == BT_SCAN_FLIPPER) || @@ -1837,7 +2575,12 @@ bool WiFiScan::mac_cmp(struct mac_addr addr1, struct mac_addr addr2) { #ifdef HAS_BT void WiFiScan::copyNimbleMac(const BLEAddress &addr, unsigned char out[6]) { - const uint8_t* bytes = addr.getNative(); // NimBLE gives MAC as uint8_t[6] + #ifndef HAS_DUAL_BAND + const uint8_t* bytes = addr.getNative(); // NimBLE gives MAC as uint8_t[6] + #else + const ble_addr_t* base_addr = addr.getBase(); + const uint8_t* bytes = base_addr->val; + #endif for (int i = 0; i < 6; i++) { out[i] = bytes[i]; } @@ -2017,17 +2760,10 @@ void WiFiScan::RunPingScan(uint8_t scan_mode, uint16_t color) this->current_scan_ip = this->gateway; Serial.println("Cleared IPs: " + (String)this->clearIPs()); if (scan_mode == WIFI_PING_SCAN) - Serial.println("Starting Ping Scan with..."); + Serial.println(F("Starting Ping Scan with...")); else if (scan_mode == WIFI_ARP_SCAN) - Serial.println("Starting ARP Scan with..."); - Serial.print("IP address: "); - Serial.println(this->ip_addr); - Serial.print("Gateway: "); - Serial.println(this->gateway); - Serial.print("Netmask: "); - Serial.println(this->subnet); - Serial.print("MAC: "); - Serial.println(WiFi.macAddress()); + Serial.println(F("Starting ARP Scan with...")); + this->showNetworkInfo(); if (scan_mode == WIFI_PING_SCAN) buffer_obj.append("Starting Ping Scan with..."); @@ -2044,9 +2780,6 @@ void WiFiScan::RunPingScan(uint8_t scan_mode, uint16_t color) buffer_obj.append("\n"); this->scan_complete = false; - - //if (scan_mode == WIFI_ARP_SCAN) - // this->fullARP(); initTime = millis(); } @@ -2124,15 +2857,8 @@ void WiFiScan::RunPortScanAll(uint8_t scan_mode, uint16_t color) (scan_mode == WIFI_SCAN_RDP)) this->current_scan_ip = this->gateway; - Serial.println("Starting Port Scan with..."); - Serial.print("IP address: "); - Serial.println(this->ip_addr); - Serial.print("Gateway: "); - Serial.println(this->gateway); - Serial.print("Netmask: "); - Serial.println(this->subnet); - Serial.print("MAC: "); - Serial.println(WiFi.macAddress()); + Serial.println(F("Starting Port Scan with...")); + this->showNetworkInfo(); buffer_obj.append("Starting Port Scan with..."); buffer_obj.append("\nSSID: " + (String)this->connected_network); @@ -2155,7 +2881,7 @@ void WiFiScan::RunLoadATList() { // Prepare to access the file File file = sd_obj.getFile("/Airtags_0.log"); if (!file) { - Serial.println("Could not open /Airtags_0.log"); + Serial.println(F("Could not open /Airtags_0.log")); #ifdef HAS_SCREEN display_obj.tft.setTextWrap(false); display_obj.tft.setFreeFont(NULL); @@ -2163,7 +2889,7 @@ void WiFiScan::RunLoadATList() { display_obj.tft.setTextSize(1); display_obj.tft.setTextColor(TFT_CYAN); - display_obj.tft.println("Could not open /Airtags_0.log"); + display_obj.tft.println(F("Could not open /Airtags_0.log")); #endif return; } @@ -2172,7 +2898,7 @@ void WiFiScan::RunLoadATList() { DynamicJsonDocument doc(10048); DeserializationError error = deserializeJson(doc, file); if (error) { - Serial.print("JSON deserialize error: "); + Serial.print(F("JSON deserialize error: ")); Serial.println(error.c_str()); file.close(); #ifdef HAS_SCREEN @@ -2182,7 +2908,7 @@ void WiFiScan::RunLoadATList() { display_obj.tft.setTextSize(1); display_obj.tft.setTextColor(TFT_CYAN); - display_obj.tft.println("Could not deserialize JSON"); + display_obj.tft.println(F("Could not deserialize JSON")); display_obj.tft.println(error.c_str()); #endif return; @@ -2212,7 +2938,7 @@ void WiFiScan::RunLoadATList() { display_obj.tft.print("Loaded Airtags: "); display_obj.tft.println((String)airtags->size()); #endif - Serial.print("Loaded Airtags:"); + Serial.print(F("Loaded Airtags:")); Serial.println((String)airtags->size()); #endif } @@ -2248,10 +2974,10 @@ void WiFiScan::RunSaveATList(bool save_as) { display_obj.tft.setTextSize(1); display_obj.tft.setTextColor(TFT_CYAN); - display_obj.tft.print("Saved Airtags: "); + display_obj.tft.print(F("Saved Airtags: ")); display_obj.tft.println((String)airtags->size()); #endif - Serial.print("Saved Airtags:"); + Serial.print(F("Saved Airtags:")); Serial.println((String)airtags->size()); } #endif @@ -2261,7 +2987,7 @@ void WiFiScan::RunLoadAPList() { #ifdef HAS_SD File file = sd_obj.getFile("/APs_0.log"); if (!file) { - Serial.println("Could not open /APs_0.log"); + Serial.println(F("Could not open /APs_0.log")); #ifdef HAS_SCREEN display_obj.tft.setTextWrap(false); display_obj.tft.setFreeFont(NULL); @@ -2276,7 +3002,7 @@ void WiFiScan::RunLoadAPList() { DynamicJsonDocument doc(10048); DeserializationError error = deserializeJson(doc, file); if (error) { - Serial.print("JSON deserialize error: "); + Serial.print(F("JSON deserialize error: ")); Serial.println(error.c_str()); file.close(); #ifdef HAS_SCREEN @@ -2285,7 +3011,7 @@ void WiFiScan::RunLoadAPList() { display_obj.tft.setCursor(0, 100); display_obj.tft.setTextSize(1); display_obj.tft.setTextColor(TFT_CYAN); - display_obj.tft.println("Could not deserialize JSON"); + display_obj.tft.println(F("Could not deserialize JSON")); display_obj.tft.println(error.c_str()); #endif return; @@ -2327,7 +3053,7 @@ void WiFiScan::RunLoadAPList() { display_obj.tft.print("Loaded APs: "); display_obj.tft.println((String)access_points->size()); #endif - Serial.print("Loaded APs:"); + Serial.print(F("Loaded APs:")); Serial.println((String)access_points->size()); #endif } @@ -2376,7 +3102,7 @@ void WiFiScan::RunSaveAPList(bool save_as) { display_obj.tft.print("Saved APs: "); display_obj.tft.println((String)access_points->size()); #endif - Serial.print("Saved APs:"); + Serial.print(F("Saved APs:")); Serial.println((String)access_points->size()); } #endif @@ -2386,7 +3112,7 @@ void WiFiScan::RunLoadSSIDList() { #ifdef HAS_SD File log_file = sd_obj.getFile("/SSIDs_0.log"); if (!log_file) { - Serial.println("Could not open /SSIDs_0.log"); + Serial.println(F("Could not open /SSIDs_0.log")); #ifdef HAS_SCREEN display_obj.tft.setTextWrap(false); display_obj.tft.setFreeFont(NULL); @@ -2394,7 +3120,7 @@ void WiFiScan::RunLoadSSIDList() { display_obj.tft.setTextSize(1); display_obj.tft.setTextColor(TFT_CYAN); - display_obj.tft.println("Could not open /SSIDs_0.log"); + display_obj.tft.println(F("Could not open /SSIDs_0.log")); #endif return; } @@ -2416,7 +3142,7 @@ void WiFiScan::RunLoadSSIDList() { log_file.close(); - Serial.print("Loaded SSIDs: "); + Serial.print(F("Loaded SSIDs: ")); Serial.println((String)ssids->size()); #endif } @@ -2445,7 +3171,7 @@ void WiFiScan::RunSaveSSIDList(bool save_as) { display_obj.tft.print("Saved SSIDs: "); display_obj.tft.println((String)ssids->size()); #endif - Serial.print("Saved SSIDs: "); + Serial.print(F("Saved SSIDs: ")); Serial.println((String)ssids->size()); } #endif @@ -2568,28 +3294,6 @@ void WiFiScan::RunAPScan(uint8_t scan_mode, uint16_t color) initTime = millis(); } -#ifdef HAS_SCREEN - void WiFiScan::RunLvJoinWiFi(uint8_t scan_mode, uint16_t color) { - - #ifdef HAS_TOUCH - display_obj.init(); - display_obj.tft.setRotation(1); - #endif - - #ifndef HAS_CYD_TOUCH - display_obj.setCalData(true); - #else - //display_obj.touchscreen.setRotation(1); - #endif - - #ifdef HAS_TOUCH - lv_obj_t * scr = lv_cont_create(NULL, NULL); - lv_disp_load_scr(scr); - #endif - - } -#endif - void WiFiScan::RunClearStations() { #ifdef HAS_SCREEN display_obj.tft.setTextWrap(false); @@ -2737,7 +3441,7 @@ void WiFiScan::logPoint(String lat, String lon, float alt, String datetime, bool } void WiFiScan::writeHeader(bool poi) { - Serial.println("Writing header to GPX file..."); + Serial.println(F("Writing header to GPX file...")); buffer_obj.append("\n"); buffer_obj.append("\n"); if (!poi) @@ -2748,7 +3452,7 @@ void WiFiScan::writeHeader(bool poi) { } void WiFiScan::writeFooter(bool poi) { - Serial.println("Writing footer to GPX file...\n"); + Serial.println(F("Writing footer to GPX file...\n")); if (!poi) { buffer_obj.append(" \n"); buffer_obj.append(" \n"); @@ -2780,7 +3484,7 @@ bool WiFiScan::RunGPSInfo(bool tracker, bool display, bool poi) { } if (display) { - Serial.println("Refreshing GPS Data on screen..."); + Serial.println(F("Refreshing GPS Data on screen...")); #ifdef HAS_SCREEN // Get screen position ready @@ -2797,10 +3501,10 @@ bool WiFiScan::RunGPSInfo(bool tracker, bool display, bool poi) { // Print the GPS data: 3 display_obj.tft.setCursor(0, SCREEN_HEIGHT / 3); if (gps_obj.getFixStatus()) - display_obj.tft.println(" Good Fix: Yes"); + display_obj.tft.println(F(" Good Fix: Yes")); else { return_val = false; - display_obj.tft.println(" Good Fix: No"); + display_obj.tft.println(F(" Good Fix: No")); } if(text != "") display_obj.tft.println(" Text: " + text); @@ -2814,11 +3518,11 @@ bool WiFiScan::RunGPSInfo(bool tracker, bool display, bool poi) { #endif // Display to serial - Serial.println("==== GPS Data ===="); + Serial.println(F("==== GPS Data ====")); if (gps_obj.getFixStatus()) - Serial.println(" Good Fix: Yes"); + Serial.println(F(" Good Fix: Yes")); else - Serial.println(" Good Fix: No"); + Serial.println(F(" Good Fix: No")); if(text != "") Serial.println(" Text: " + text); @@ -2991,23 +3695,23 @@ void WiFiScan::RunAPInfo(uint16_t index, bool do_display) { Serial.print("Security: "); switch (sec) { - case WIFI_SECURITY_OPEN: Serial.println("Open"); break; - case WIFI_SECURITY_WEP: Serial.println("WEP"); break; - case WIFI_SECURITY_WPA: Serial.println("WPA"); break; - case WIFI_SECURITY_WPA2: Serial.println("WPA2"); break; - case WIFI_SECURITY_WPA3: Serial.println("WPA3"); break; - case WIFI_SECURITY_WPA_WPA2_MIXED: Serial.println("WPA/WPA2 Mixed"); break; - case WIFI_SECURITY_WPA2_ENTERPRISE: Serial.println("WPA2 Enterprise"); break; - case WIFI_SECURITY_WPA3_ENTERPRISE: Serial.println("WPA3 Enterprise"); break; - case WIFI_SECURITY_WAPI: Serial.println("WAPI"); break; - default: Serial.println("Unknown"); break; + case WIFI_SECURITY_OPEN: Serial.println(F("Open")); break; + case WIFI_SECURITY_WEP: Serial.println(F("WEP")); break; + case WIFI_SECURITY_WPA: Serial.println(F("WPA")); break; + case WIFI_SECURITY_WPA2: Serial.println(F("WPA2")); break; + case WIFI_SECURITY_WPA3: Serial.println(F("WPA3")); break; + case WIFI_SECURITY_WPA_WPA2_MIXED: Serial.println(F("WPA/WPA2 Mixed")); break; + case WIFI_SECURITY_WPA2_ENTERPRISE: Serial.println(F("WPA2 Enterprise")); break; + case WIFI_SECURITY_WPA3_ENTERPRISE: Serial.println(F("WPA3 Enterprise")); break; + case WIFI_SECURITY_WAPI: Serial.println(F("WAPI")); break; + default: Serial.println(F("Unknown")); break; } - Serial.print(" WPS: "); + Serial.print(F(" WPS: ")); switch (wps) { - case true: Serial.println("true"); break; - case false: Serial.println("false"); break; - default: Serial.println("false"); break; + case true: Serial.println(F("true")); break; + case false: Serial.println(F("false")); break; + default: Serial.println(F("false")); break; } #ifdef HAS_SCREEN @@ -3022,40 +3726,40 @@ void WiFiScan::RunAPInfo(uint16_t index, bool do_display) { display_obj.tft.print("Security: "); switch (sec) { - case WIFI_SECURITY_OPEN: display_obj.tft.println("Open"); break; - case WIFI_SECURITY_WEP: display_obj.tft.println("WEP"); break; - case WIFI_SECURITY_WPA: display_obj.tft.println("WPA"); break; - case WIFI_SECURITY_WPA2: display_obj.tft.println("WPA2"); break; - case WIFI_SECURITY_WPA3: display_obj.tft.println("WPA3"); break; - case WIFI_SECURITY_WPA_WPA2_MIXED: display_obj.tft.println("WPA/WPA2 Mixed"); break; - case WIFI_SECURITY_WPA2_ENTERPRISE: display_obj.tft.println("WPA2 Enterprise"); break; - case WIFI_SECURITY_WPA3_ENTERPRISE: display_obj.tft.println("WPA3 Enterprise"); break; - case WIFI_SECURITY_WAPI: display_obj.tft.println("WAPI"); break; - default: display_obj.tft.println("Unknown"); break; + case WIFI_SECURITY_OPEN: display_obj.tft.println(F("Open")); break; + case WIFI_SECURITY_WEP: display_obj.tft.println(F("WEP")); break; + case WIFI_SECURITY_WPA: display_obj.tft.println(F("WPA")); break; + case WIFI_SECURITY_WPA2: display_obj.tft.println(F("WPA2")); break; + case WIFI_SECURITY_WPA3: display_obj.tft.println(F("WPA3")); break; + case WIFI_SECURITY_WPA_WPA2_MIXED: display_obj.tft.println(F("WPA/WPA2 Mixed")); break; + case WIFI_SECURITY_WPA2_ENTERPRISE: display_obj.tft.println(F("WPA2 Enterprise")); break; + case WIFI_SECURITY_WPA3_ENTERPRISE: display_obj.tft.println(F("WPA3 Enterprise")); break; + case WIFI_SECURITY_WAPI: display_obj.tft.println(F("WAPI")); break; + default: display_obj.tft.println(F("Unknown")); break; } display_obj.tft.print(" WPS: "); switch (wps) { - case true: display_obj.tft.println("true"); break; - case false: display_obj.tft.println("false"); break; - default: display_obj.tft.println("false"); break; + case true: display_obj.tft.println(F("true")); break; + case false: display_obj.tft.println(F("false")); break; + default: display_obj.tft.println(F("false")); break; } } #endif if (!access_points->get(index).selected) { - Serial.println("Selected: false"); + Serial.println(F("Selected: false")); #ifdef HAS_SCREEN if (do_display) { - display_obj.tft.println("Selected: false"); + display_obj.tft.println(F("Selected: false")); } #endif } else { - Serial.println("Selected: true"); + Serial.println(F("Selected: true")); #ifdef HAS_SCREEN if (do_display) { - display_obj.tft.println("Selected: true"); + display_obj.tft.println(F("Selected: true")); } #endif } @@ -3270,7 +3974,7 @@ void WiFiScan::RunPacketMonitor(uint8_t scan_mode, uint16_t color) #endif #endif - Serial.println("Running packet scan..."); + Serial.println(F("Running packet scan...")); esp_wifi_init(&cfg2); #ifdef HAS_DUAL_BAND esp_wifi_set_country(&country); @@ -3366,7 +4070,7 @@ void WiFiScan::RunEapolScan(uint8_t scan_mode, uint16_t color) err = esp_wifi_set_protocol(WIFI_IF_AP, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_LR); if (err != 0) { - Serial.print("could not set protocol : err=0x"); + Serial.print(F("could not set protocol : err=0x")); Serial.println(err, HEX); } @@ -3381,7 +4085,7 @@ void WiFiScan::RunEapolScan(uint8_t scan_mode, uint16_t color) err = esp_wifi_set_config((wifi_interface_t)WIFI_IF_AP, &conf); if (err != 0) { - Serial.print("AP config set error, Maurauder SSID might visible : err=0x"); + Serial.print(F("AP config set error, Maurauder SSID might visible : err=0x")); Serial.println(err, HEX); } @@ -3613,16 +4317,18 @@ void WiFiScan::executeSourApple() { void WiFiScan::setBaseMacAddress(uint8_t macAddr[6]) { // Use ESP-IDF function to set the base MAC address - esp_err_t err = esp_base_mac_addr_set(macAddr); + #ifndef HAS_DUAL_BAND + esp_err_t err = esp_base_mac_addr_set(macAddr); - // Check for success or handle errors - if (err == ESP_OK) { - return; - } else if (err == ESP_ERR_INVALID_ARG) { - Serial.println("Error: Invalid MAC address argument."); - } else { - Serial.printf("Error: Failed to set MAC address. Code: %d\n", err); - } + // Check for success or handle errors + if (err == ESP_OK) { + return; + } else if (err == ESP_ERR_INVALID_ARG) { + Serial.println(F("Error: Invalid MAC address argument.")); + } else { + Serial.printf("Error: Failed to set MAC address. Code: %d\n", err); + } + #endif } void WiFiScan::executeSpoofAirtag() { @@ -3694,7 +4400,7 @@ void WiFiScan::executeWarDrive() { String display_string; while (WiFi.scanComplete() == WIFI_SCAN_RUNNING) { - Serial.println("Scan running..."); + Serial.println(F("Scan running...")); delay(500); } @@ -3889,10 +4595,10 @@ void WiFiScan::RunStationScan(uint8_t scan_mode, uint16_t color) if (err != ESP_OK) { Serial.printf("Default config also failed (0x%04X)\n", err); } else { - Serial.println("Wi-Fi init succeeded with default config."); + Serial.println(F("Wi-Fi init succeeded with default config.")); } } else { - Serial.println("Wi-Fi init succeeded with custom config."); + Serial.println(F("Wi-Fi init succeeded with custom config.")); } #ifdef HAS_DUAL_BAND esp_wifi_set_country(&country); @@ -3975,7 +4681,7 @@ void WiFiScan::RunRawScan(uint8_t scan_mode, uint16_t color) this->setMac(); esp_wifi_set_promiscuous(true); esp_wifi_set_promiscuous_filter(&filt); - esp_wifi_set_promiscuous_rx_cb(&rawSnifferCallback); + esp_wifi_set_promiscuous_rx_cb(&beaconSnifferCallback); esp_wifi_set_channel(set_channel, WIFI_SECOND_CHAN_NONE); this->wifi_initialized = true; initTime = millis(); @@ -4036,10 +4742,13 @@ void WiFiScan::RunDeauthScan(uint8_t scan_mode, uint16_t color) // Function for running probe request scan void WiFiScan::RunProbeScan(uint8_t scan_mode, uint16_t color) { - probe_req_ssids->clear(); + if (scan_mode == WIFI_SCAN_PROBE) + probe_req_ssids->clear(); if (scan_mode == WIFI_SCAN_PROBE) startPcap("probe"); + else if (scan_mode == BT_SCAN_FLOCK) + startPcap("flock"); else if (scan_mode == WIFI_SCAN_STATION_WAR_DRIVE) { #ifdef HAS_GPS if (gps_obj.getGpsModuleStatus()) { @@ -4074,7 +4783,12 @@ void WiFiScan::RunProbeScan(uint8_t scan_mode, uint16_t color) display_obj.tft.setTextColor(TFT_BLACK, color); #ifdef HAS_FULL_SCREEN display_obj.tft.fillRect(0,16,TFT_WIDTH,16, color); - display_obj.tft.drawCentreString(text_table4[40],TFT_WIDTH / 2,16,2); + if (scan_mode != BT_SCAN_FLOCK) + display_obj.tft.drawCentreString(text_table4[40],TFT_WIDTH / 2,16,2); + else { + Serial.println(F("Starting WiFi sniff for Flock...")); + display_obj.tft.drawCentreString("Flock Sniff",TFT_WIDTH / 2,16,2); + } #endif #ifdef HAS_ILI9341 display_obj.touchToExit(); @@ -4094,7 +4808,7 @@ void WiFiScan::RunProbeScan(uint8_t scan_mode, uint16_t color) this->setMac(); esp_wifi_set_promiscuous(true); esp_wifi_set_promiscuous_filter(&filt); - esp_wifi_set_promiscuous_rx_cb(&probeSnifferCallback); + esp_wifi_set_promiscuous_rx_cb(&beaconSnifferCallback); esp_wifi_set_channel(set_channel, WIFI_SECOND_CHAN_NONE); this->wifi_initialized = true; initTime = millis(); @@ -4190,20 +4904,19 @@ void WiFiScan::RunBluetoothScan(uint8_t scan_mode, uint16_t color) display_obj.print_delay_1 = 50; display_obj.print_delay_2 = 20; #endif - - if (scan_mode != BT_SCAN_WAR_DRIVE_CONT) { + + if ((scan_mode == BT_SCAN_FLOCK) || + (scan_mode == BT_SCAN_FLOCK_WARDRIVE) || + (scan_mode == BT_SCAN_SIMPLE) || + (scan_mode == BT_SCAN_SIMPLE_TWO) || + (scan_mode == BT_SCAN_WAR_DRIVE_CONT) || + (scan_mode == BT_SCAN_ANALYZER)) + NimBLEDevice::setScanDuplicateCacheSize(0); + else { NimBLEDevice::setScanFilterMode(CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE); NimBLEDevice::setScanDuplicateCacheSize(200); } - else if ((scan_mode == BT_SCAN_WAR_DRIVE_CONT) || (scan_mode == BT_SCAN_ANALYZER)) { - NimBLEDevice::setScanDuplicateCacheSize(0); - } - if ((scan_mode == BT_SCAN_FLOCK) || (scan_mode == BT_SCAN_FLOCK_WARDRIVE)) - NimBLEDevice::setScanDuplicateCacheSize(0); - - if ((scan_mode == BT_SCAN_SIMPLE) || (scan_mode == BT_SCAN_SIMPLE_TWO)) - NimBLEDevice::setScanDuplicateCacheSize(0); NimBLEDevice::init(""); pBLEScan = NimBLEDevice::getScan(); //create new scan @@ -4248,26 +4961,28 @@ void WiFiScan::RunBluetoothScan(uint8_t scan_mode, uint16_t color) display_obj.setupScrollArea(display_obj.TOP_FIXED_AREA_2, BOT_FIXED_AREA); #endif if (scan_mode == BT_SCAN_ALL) - pBLEScan->setAdvertisedDeviceCallbacks(new bluetoothScanAllCallback(), false); - else if ((scan_mode == BT_SCAN_AIRTAG) || (scan_mode == BT_SCAN_AIRTAG_MON)) { - this->clearAirtags(); - pBLEScan->setAdvertisedDeviceCallbacks(new bluetoothScanAllCallback(), true); - } - else if (scan_mode == BT_SCAN_FLIPPER) { - this->clearFlippers(); - pBLEScan->setAdvertisedDeviceCallbacks(new bluetoothScanAllCallback(), true); - } - else if (scan_mode == BT_SCAN_FLOCK) { - pBLEScan->setAdvertisedDeviceCallbacks(new bluetoothScanAllCallback(), true); - } - else if (scan_mode == BT_SCAN_FLOCK_WARDRIVE) { - pBLEScan->setAdvertisedDeviceCallbacks(new bluetoothScanAllCallback(), true); - } - else if (scan_mode == BT_SCAN_SIMPLE) { - pBLEScan->setAdvertisedDeviceCallbacks(new bluetoothScanAllCallback(), true); - } - else if (scan_mode == BT_SCAN_SIMPLE_TWO) { - pBLEScan->setAdvertisedDeviceCallbacks(new bluetoothScanAllCallback(), false); + #ifndef HAS_DUAL_BAND + pBLEScan->setAdvertisedDeviceCallbacks(new bluetoothScanAllCallback(), false); + #else + pBLEScan->setScanCallbacks(new bluetoothScanAllCallback(), false); + #endif + else if ((scan_mode == BT_SCAN_FLIPPER) || + (scan_mode == BT_SCAN_FLOCK) || + (scan_mode == BT_SCAN_FLOCK_WARDRIVE) || + (scan_mode == BT_SCAN_SIMPLE) || + (scan_mode == BT_SCAN_AIRTAG) || + (scan_mode == BT_SCAN_AIRTAG_MON) || + (scan_mode == BT_SCAN_SIMPLE_TWO)) { + if (scan_mode == BT_SCAN_FLIPPER) + this->clearFlippers(); + if ((scan_mode == BT_SCAN_AIRTAG) || (scan_mode == BT_SCAN_AIRTAG_MON)) + this->clearAirtags(); + + #ifndef HAS_DUAL_BAND + pBLEScan->setAdvertisedDeviceCallbacks(new bluetoothScanAllCallback(), true); + #else + pBLEScan->setScanCallbacks(new bluetoothScanAllCallback(), true); + #endif } } else if ((scan_mode == BT_SCAN_WAR_DRIVE) || (scan_mode == BT_SCAN_WAR_DRIVE_CONT) || (scan_mode == BT_SCAN_FLOCK_WARDRIVE)) { @@ -4310,9 +5025,18 @@ void WiFiScan::RunBluetoothScan(uint8_t scan_mode, uint16_t color) display_obj.setupScrollArea(display_obj.TOP_FIXED_AREA_2, BOT_FIXED_AREA); #endif if (scan_mode != BT_SCAN_WAR_DRIVE_CONT) - pBLEScan->setAdvertisedDeviceCallbacks(new bluetoothScanAllCallback(), false); + #ifndef HAS_DUAL_BAND + pBLEScan->setAdvertisedDeviceCallbacks(new bluetoothScanAllCallback(), false); + #else + pBLEScan->setScanCallbacks(new bluetoothScanAllCallback(), false); + #endif else - pBLEScan->setAdvertisedDeviceCallbacks(new bluetoothScanAllCallback(), true); + #ifndef HAS_DUAL_BAND + pBLEScan->setAdvertisedDeviceCallbacks(new bluetoothScanAllCallback(), true); + #else + pBLEScan->setScanCallbacks(new bluetoothScanAllCallback(), true); + #endif + } else if (scan_mode == BT_SCAN_SKIMMERS) { @@ -4329,7 +5053,11 @@ void WiFiScan::RunBluetoothScan(uint8_t scan_mode, uint16_t color) display_obj.tft.setTextColor(TFT_BLACK, TFT_DARKGREY); display_obj.setupScrollArea(display_obj.TOP_FIXED_AREA_2, BOT_FIXED_AREA); #endif - pBLEScan->setAdvertisedDeviceCallbacks(new bluetoothScanSkimmersCallback(), false); + #ifndef HAS_DUAL_BAND + pBLEScan->setAdvertisedDeviceCallbacks(new bluetoothScanAllCallback(), false); + #else + pBLEScan->setScanCallbacks(new bluetoothScanAllCallback(), false); + #endif } else if (scan_mode == BT_SCAN_ANALYZER) { #ifdef HAS_SCREEN @@ -4348,7 +5076,12 @@ void WiFiScan::RunBluetoothScan(uint8_t scan_mode, uint16_t color) display_obj.tft.setTextColor(TFT_CYAN, TFT_BLACK); display_obj.setupScrollArea(display_obj.TOP_FIXED_AREA_2, BOT_FIXED_AREA); #endif - pBLEScan->setAdvertisedDeviceCallbacks(new bluetoothScanAllCallback(), false); + #ifndef HAS_DUAL_BAND + pBLEScan->setAdvertisedDeviceCallbacks(new bluetoothScanAllCallback(), false); + #else + pBLEScan->setScanCallbacks(new bluetoothScanAllCallback(), false); + #endif + } pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster pBLEScan->setInterval(100); @@ -4362,7 +5095,7 @@ void WiFiScan::RunBluetoothScan(uint8_t scan_mode, uint16_t color) (scan_mode == BT_SCAN_FLOCK_WARDRIVE)) pBLEScan->setDuplicateFilter(false); pBLEScan->start(0, scanCompleteCB, false); - Serial.println("Started BLE Scan"); + Serial.println(F("Started BLE Scan")); this->ble_initialized = true; #ifdef HAS_FLIPPER_LED @@ -4427,16 +5160,16 @@ void WiFiScan::pwnSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type) delay(random(0, 10)); - Serial.print("RSSI: "); + Serial.print(F("RSSI: ")); Serial.print(snifferPacket->rx_ctrl.rssi); - Serial.print(" Ch: "); + Serial.print(F(" Ch: ")); Serial.print(snifferPacket->rx_ctrl.channel); - Serial.print(" BSSID: "); + Serial.print(F(" BSSID: ")); Serial.print(addr); //display_string.concat(addr); display_string.concat("CH: " + (String)snifferPacket->rx_ctrl.channel); - Serial.print(" ESSID: "); - display_string.concat(" -> "); + Serial.print(F(" ESSID: ")); + display_string.concat(F(" -> ")); // Just grab the first 255 bytes of the pwnagotchi beacon // because that is where the name is @@ -4459,11 +5192,11 @@ void WiFiScan::pwnSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type) //JsonObject& json = jsonBuffer.parseObject(essid); // ArduinoJson v5 // ArduinoJson v6 if (deserializeJson(json, essid)) { - Serial.println("\nCould not parse Pwnagotchi json"); + Serial.println(F("\nCould not parse Pwnagotchi json")); display_string.concat(essid); } else { - Serial.println("\nSuccessfully parsed json"); + Serial.println(F("\nSuccessfully parsed json")); String json_output; //json.printTo(json_output); // ArduinoJson v5 serializeJson(json, json_output); // ArduinoJson v6 @@ -4633,11 +5366,11 @@ void WiFiScan::apSnifferCallbackFull(void* buf, wifi_promiscuous_pkt_type_t type if (in_list < 0) { - Serial.print("RSSI: "); + Serial.print(F("RSSI: ")); Serial.print(snifferPacket->rx_ctrl.rssi); - Serial.print(" Ch: "); + Serial.print(F(" Ch: ")); Serial.print(snifferPacket->rx_ctrl.channel); - Serial.print(" BSSID: "); + Serial.print(F(" BSSID: ")); Serial.print(addr); #ifdef HAS_SCREEN display_string.concat("#"); @@ -4651,7 +5384,7 @@ void WiFiScan::apSnifferCallbackFull(void* buf, wifi_promiscuous_pkt_type_t type display_string.concat(" "); #endif - Serial.print(" ESSID: "); + Serial.print(F(" ESSID: ")); if (snifferPacket->payload[37] <= 0) display_string.concat(addr); else { @@ -4711,7 +5444,7 @@ void WiFiScan::apSnifferCallbackFull(void* buf, wifi_promiscuous_pkt_type_t type //ap.beacon->add(snifferPacket->payload[34]); //ap.beacon->add(snifferPacket->payload[35]); - Serial.print("\nBeacon: "); + Serial.print(F("\nBeacon: ")); for (int i = 0; i < 2; i++) { char hexCar[4]; @@ -4855,21 +5588,22 @@ void WiFiScan::apSnifferCallbackFull(void* buf, wifi_promiscuous_pkt_type_t type char sta_addr[] = "00:00:00:00:00:00"; if (ap_is_src) { - Serial.print("ap: "); + Serial.print(F("ap: ")); Serial.print(ap_addr); - Serial.print(" -> sta: "); + Serial.print(F(" -> sta: ")); getMAC(sta_addr, snifferPacket->payload, 4); Serial.println(sta_addr); } else { - Serial.print("sta: "); + Serial.print(F("sta: ")); getMAC(sta_addr, snifferPacket->payload, 10); Serial.print(sta_addr); - Serial.print(" -> ap: "); + Serial.print(F(" -> ap: ")); Serial.println(ap_addr); } - display_string.concat(replaceOUIWithManufacturer(sta_addr)); + //display_string.concat(replaceOUIWithManufacturer(sta_addr)); + display_string.concat(sta_addr); display_string.concat(" -> "); display_string.concat(access_points->get(ap_index).essid); @@ -5030,8 +5764,6 @@ void WiFiScan::apSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type) { extern WiFiScan wifi_scan_obj; 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 = ""; @@ -5041,9 +5773,6 @@ void WiFiScan::apSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type) 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 #ifdef HAS_SCREEN @@ -5078,14 +5807,14 @@ void WiFiScan::apSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type) if (!in_list) { delay(random(0, 10)); - Serial.print("RSSI: "); + Serial.print(F("RSSI: ")); Serial.print(snifferPacket->rx_ctrl.rssi); - Serial.print(" Ch: "); + Serial.print(F(" Ch: ")); Serial.print(snifferPacket->rx_ctrl.channel); - Serial.print(" BSSID: "); + Serial.print(F(" BSSID: ")); Serial.print(addr); display_string.concat(addr); - Serial.print(" ESSID: "); + Serial.print(F(" ESSID: ")); display_string.concat(" -> "); for (int i = 0; i < snifferPacket->payload[37]; i++) { @@ -5180,7 +5909,7 @@ String WiFiScan::processPwnagotchiBeacon(const uint8_t* frame, int length) { while (jsonEndIndex > jsonStartIndex && frame[jsonEndIndex - 1] != '}') jsonEndIndex--; if (jsonStartIndex >= jsonEndIndex) { - Serial.println("JSON payload not found."); + Serial.println(F("JSON payload not found.")); return ""; } @@ -5192,7 +5921,7 @@ String WiFiScan::processPwnagotchiBeacon(const uint8_t* frame, int length) { // Check if we have enough memory before creating StaticJsonDocument if (jsonCapacity > ESP.getFreeHeap()) { - Serial.println("Insufficient memory to parse JSON."); + Serial.println(F("Insufficient memory to parse JSON.")); return ""; } @@ -5201,7 +5930,7 @@ String WiFiScan::processPwnagotchiBeacon(const uint8_t* frame, int length) { DeserializationError error = deserializeJson(doc, jsonString); if (error) { - Serial.print("Failed to parse JSON: "); + Serial.print(F("Failed to parse JSON: ")); Serial.println(error.c_str()); return ""; } @@ -5215,9 +5944,9 @@ String WiFiScan::processPwnagotchiBeacon(const uint8_t* frame, int length) { int uptime = doc["uptime"]; // Print and return the Pwnagotchi name and pwnd_tot - Serial.print("Pwnagotchi Name: "); + Serial.print(F("Pwnagotchi Name: ")); Serial.println(name); - Serial.print("Pwnd Totals: "); + Serial.print(F("Pwnd Totals: ")); Serial.println(pwnd_tot); #ifdef HAS_SCREEN @@ -5235,7 +5964,7 @@ String WiFiScan::processPwnagotchiBeacon(const uint8_t* frame, int length) { return String("Pwnagotchi: ") + name + ", \nPwnd: " + String(pwnd_tot) + ", \nVer: " + ver; } else { - Serial.println("Not a Pwnagotchi frame."); + Serial.println(F("Not a Pwnagotchi frame.")); return ""; } } @@ -5466,10 +6195,10 @@ void WiFiScan::pineScanSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t ty // Check if we've reached the maximum number of tracked APs if (wifi_scan_obj.pinescan_trackers->size() >= MAX_AP_ENTRIES) { if (!wifi_scan_obj.pinescan_list_full_reported) { - Serial.println("AP List Full - Clearing list to make room"); + Serial.println(F("AP List Full - Clearing list to make room")); wifi_scan_obj.pinescan_list_full_reported = true; wifi_scan_obj.pinescan_trackers->clear(); - Serial.println("AP list cleared, continuing scan"); + Serial.println(F("AP list cleared, continuing scan")); } // Add the current AP to the freshly cleared list @@ -5520,8 +6249,8 @@ void WiFiScan::pineScanSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t ty if (pinescan_match) { if (wifi_scan_obj.confirmed_pinescan->size() >= MAX_PINESCAN_ENTRIES) { if (!wifi_scan_obj.pinescan_list_full_reported) { - Serial.println("Confirmed PineScan List Full - Cannot add more"); - Serial.println("Stopping PineScan detection until scan is restarted"); + Serial.println(F("Confirmed PineScan List Full - Cannot add more")); + Serial.println(F("Stopping PineScan detection until scan is restarted")); wifi_scan_obj.pinescan_list_full_reported = true; } return; // Stop processing completely if list is full @@ -5790,8 +6519,8 @@ void WiFiScan::multiSSIDSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t t if (ap_index == -1) { if (wifi_scan_obj.confirmed_multissid->size() >= MAX_MULTISSID_ENTRIES) { if (!wifi_scan_obj.multissid_list_full_reported) { - Serial.println("Confirmed MultiSSID List Full - Cannot add more"); - Serial.println("Stopping MultiSSID detection until scan is restarted"); + Serial.println(F("Confirmed MultiSSID List Full - Cannot add more")); + Serial.println(F("Stopping MultiSSID detection until scan is restarted")); wifi_scan_obj.multissid_list_full_reported = true; } return; // Stop processing completely if list is full @@ -5800,10 +6529,10 @@ void WiFiScan::multiSSIDSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t t // Check if we have reached the maximum number of tracked APs if (wifi_scan_obj.multissid_trackers->size() >= MAX_AP_ENTRIES) { if (!wifi_scan_obj.multissid_list_full_reported) { - Serial.println("AP List Full - Clearing list to make room"); + Serial.println(F("AP List Full - Clearing list to make room")); wifi_scan_obj.multissid_list_full_reported = true; wifi_scan_obj.multissid_trackers->clear(); - Serial.println("AP list cleared, continuing scan"); + Serial.println(F("AP list cleared, continuing scan")); } // Add the current AP to the freshly cleared list @@ -5916,223 +6645,511 @@ void WiFiScan::beaconSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type #endif 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; + uint8_t src_addr[] = {snifferPacket->payload[10], + snifferPacket->payload[11], + snifferPacket->payload[12], + snifferPacket->payload[13], + snifferPacket->payload[14], + snifferPacket->payload[15]}; + + uint8_t dst_addr[] = {snifferPacket->payload[4], + snifferPacket->payload[5], + snifferPacket->payload[6], + snifferPacket->payload[7], + snifferPacket->payload[8], + snifferPacket->payload[9]}; + String display_string = ""; 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 ((wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) || + (wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION_WAR_DRIVE) || + (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) || + (wifi_scan_obj.currentScanMode == WIFI_SCAN_PWN)) { + if (type == WIFI_PKT_MGMT) { + len -= 4; + const wifi_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)snifferPacket->payload; - // If we dont the buffer size is not 0, don't write or else we get CORRUPT_HEAP - #ifdef HAS_SCREEN - int buff = display_obj.display_buffer->size(); - #else - int buff = 0; - #endif - uint8_t target_mac[6] = {0xde, 0xad, 0xbe, 0xef, 0xde, 0xad}; + uint8_t target_mac[6] = {0xde, 0xad, 0xbe, 0xef, 0xde, 0xad}; - // It is a beacon - if ((snifferPacket->payload[0] == 0x80) && (buff == 0)) + // It is a beacon + if (snifferPacket->payload[0] == 0x80) { + bool mac_match = true; + for (int i = 0; i < 6; i++) { + if (src_addr[i] != target_mac[i]) { + mac_match = false; + break; + } + } + + // If MAC matches, call processPwnagotchiBeacon with frame data + if (mac_match) { + Serial.println(F("Pwnagotchi beacon detected!")); + wifi_scan_obj.processPwnagotchiBeacon(snifferPacket->payload, len); + return; + } + + if (wifi_scan_obj.currentScanMode == WIFI_SCAN_PWN) { + buffer_obj.append(snifferPacket, len); + return; + } + + // Do signal strength stuff first + else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN) { + bool found = false; + uint8_t targ_index = 0; + AccessPoint targ_ap; + + // Check list of APs + for (int i = 0; i < access_points->size(); i++) { + if (access_points->get(i).selected) { + // Compare AP bssid to ssid of recvd packet + for (int x = 0; x < 6; x++) { + if (src_addr[x] != access_points->get(i).bssid[x]) { + found = false; + break; + } + else + found = true; + } + if (found) { + targ_ap = access_points->get(i); + targ_index = i; + break; + } + } + } + if (!found) + return; + + if ((targ_ap.rssi + 5 < snifferPacket->rx_ctrl.rssi) || (snifferPacket->rx_ctrl.rssi + 5 < targ_ap.rssi)) { + targ_ap.rssi = snifferPacket->rx_ctrl.rssi; + access_points->set(targ_index, targ_ap); + Serial.println((String)access_points->get(targ_index).essid + " RSSI: " + (String)access_points->get(targ_index).rssi); + display_string.concat((String)access_points->get(targ_index).essid); + display_string.concat(" RSSI: "); + display_string.concat((String)access_points->get(targ_index).rssi); + int temp_len = display_string.length(); + for (int i = 0; i < 50 - temp_len; i++) + { + display_string.concat(" "); + } + #ifdef HAS_SCREEN + display_obj.display_buffer->add(display_string); + #endif + return; + } + } + + else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) { + delay(random(0, 10)); + Serial.print(F("RSSI: ")); + Serial.print(snifferPacket->rx_ctrl.rssi); + Serial.print(F(" Ch: ")); + Serial.print(snifferPacket->rx_ctrl.channel); + Serial.print(F(" BSSID: ")); + char addr[] = "00:00:00:00:00:00"; + getMAC(addr, snifferPacket->payload, 10); + Serial.print(addr); + Serial.print(" ESSID Len: " + (String)snifferPacket->payload[37]); + Serial.print(F(" ESSID: ")); + #ifdef HAS_FULL_SCREEN + display_string.concat(snifferPacket->rx_ctrl.rssi); + display_string.concat(" "); + display_string.concat(snifferPacket->rx_ctrl.channel); + display_string.concat(" "); + #endif + if (snifferPacket->payload[37] <= 0) + display_string.concat(addr); + else { + for (int i = 0; i < snifferPacket->payload[37]; i++) + { + Serial.print((char)snifferPacket->payload[i + 38]); + display_string.concat((char)snifferPacket->payload[i + 38]); + } + } + + int temp_len = display_string.length(); + + #ifdef HAS_SCREEN + for (int i = 0; i < 40 - temp_len; i++) + { + display_string.concat(" "); + } + + Serial.print(" "); + + display_obj.display_buffer->add(display_string); + #endif + + Serial.println(); + + buffer_obj.append(snifferPacket, len); + } + else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_WAR_DRIVE) { + #ifdef HAS_GPS + if (gps_obj.getGpsModuleStatus()) { + bool do_save = false; + + // Check if we've already seen this AP + char addr[] = "00:00:00:00:00:00"; + getMAC(addr, snifferPacket->payload, 10); + if (wifi_scan_obj.seen_mac(reinterpret_cast(addr))) + return; + + Serial.print(F("RSSI: ")); + Serial.print(snifferPacket->rx_ctrl.rssi); + Serial.print(F(" Ch: ")); + Serial.print(snifferPacket->rx_ctrl.channel); + + if (snifferPacket->payload[37] > 0) { + Serial.print(F(" ESSID: ")); + for (int i = 0; i < snifferPacket->payload[37]; i++) + { + Serial.print((char)snifferPacket->payload[i + 38]); + display_string.concat((char)snifferPacket->payload[i + 38]); + essid.concat((char)snifferPacket->payload[i + 38]); + } + } + else { + Serial.print(F(" BSSID: ")); + Serial.print(addr); + display_string.concat(addr); + } + + if (gps_obj.getFixStatus()) { + do_save = true; + display_string.concat(" | Lt: " + gps_obj.getLat()); + display_string.concat(" | Ln: " + gps_obj.getLon()); + } + else + display_string.concat(" | GPS: No Fix"); + + int temp_len = display_string.length(); + + #ifdef HAS_SCREEN + for (int i = 0; i < 40 - temp_len; i++) + { + display_string.concat(" "); + } + + Serial.print(" "); + + display_obj.display_buffer->add(display_string); + #endif + + Serial.println(); + + wifi_scan_obj.save_mac(reinterpret_cast(addr)); + + int n = WiFi.scanNetworks(false, true, false, 110, wifi_scan_obj.set_channel); + + if (do_save) { + if (n > 0) { + for (int i = 0; i < n; i++) { + Serial.printf("%-32.32s", WiFi.SSID(i).c_str()); + Serial.print(F(" -> ")); + Serial.println(wifi_scan_obj.security_int_to_string(WiFi.encryptionType(i)).c_str()); + } + } + String wardrive_line = (String)addr + "," + essid + "," + wifi_scan_obj.security_int_to_string(snifferPacket->rx_ctrl.channel) + "," + gps_obj.getDatetime() + "," + (String)snifferPacket->rx_ctrl.channel + "," + (String)snifferPacket->rx_ctrl.rssi + "," + gps_obj.getLat() + "," + gps_obj.getLon() + "," + gps_obj.getAlt() + "," + gps_obj.getAccuracy() + ",WIFI"; + Serial.println(wardrive_line); + //buffer_obj.append(wardrive_line); + } + } + #endif + } + } + else if (snifferPacket->payload[0] == 0x40) { + if (wifi_scan_obj.currentScanMode == WIFI_SCAN_PROBE) { + String probe_req_essid; + + delay(random(0, 10)); + Serial.print(F("RSSI: ")); + Serial.print(snifferPacket->rx_ctrl.rssi); + Serial.print(F(" Ch: ")); + Serial.print(snifferPacket->rx_ctrl.channel); + Serial.print(F(" Client: ")); + char addr[] = "00:00:00:00:00:00"; + getMAC(addr, snifferPacket->payload, 10); + Serial.print(addr); + display_string.concat(addr); + Serial.print(F(" Requesting: ")); + display_string.concat(" -> "); + for (int i = 0; i < snifferPacket->payload[25]; i++) + { + Serial.print((char)snifferPacket->payload[26 + i]); + probe_req_essid.concat((char)snifferPacket->payload[26 + i]); + } + + display_string.concat(probe_req_essid); + + if (probe_req_essid.length() > 0) { + bool essidExist = false; + for (int i = 0; i < probe_req_ssids->size(); i++) { + ProbeReqSsid cur_probe_ssid = probe_req_ssids->get(i); + if (cur_probe_ssid.essid == probe_req_essid) { + cur_probe_ssid.requests++; + probe_req_ssids->set(i, cur_probe_ssid); + essidExist = true; + break; + } + } + if (!essidExist) { + ProbeReqSsid probeReqSsid; + probeReqSsid.essid = probe_req_essid; + probeReqSsid.requests = 1; + probeReqSsid.selected = false; + probe_req_ssids->add(probeReqSsid); + } + } + // Print spaces because of the rotating lines of the hardware scroll. + // The same characters print from previous lines so I just overwrite them + // with spaces. + #ifdef HAS_SCREEN + for (int i = 0; i < 19 - snifferPacket->payload[25]; i++) + { + display_string.concat(" "); + } + + display_obj.display_buffer->add(display_string); + #endif + + Serial.println(); + + buffer_obj.append(snifferPacket, len); + } + else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION_WAR_DRIVE) { + #ifdef HAS_GPS + if (gps_obj.getGpsModuleStatus()) { + bool do_save = false; + + // Check if we've already seen this AP + char addr[] = "00:00:00:00:00:00"; + getMAC(addr, snifferPacket->payload, 10); + if (wifi_scan_obj.seen_mac(reinterpret_cast(addr))) + return; + + Serial.print(F("RSSI: ")); + Serial.print(snifferPacket->rx_ctrl.rssi); + Serial.print(F(" Ch: ")); + Serial.print(snifferPacket->rx_ctrl.channel); + + Serial.print(F(" BSSID: ")); + Serial.print(addr); + display_string.concat(addr); + + if (gps_obj.getFixStatus()) { + do_save = true; + display_string.concat(" | Lt: " + gps_obj.getLat()); + display_string.concat(" | Ln: " + gps_obj.getLon()); + } + else + display_string.concat(" | GPS: No Fix"); + + int temp_len = display_string.length(); + + #ifdef HAS_SCREEN + for (int i = 0; i < 40 - temp_len; i++) + { + display_string.concat(" "); + } + + Serial.print(" "); + + + display_obj.display_buffer->add(display_string); + #endif + + Serial.println(); + + //wifi_scan_obj.save_mac(reinterpret_cast(addr)); + + if (do_save) { + String wardrive_line = (String)addr + "," + (String)addr + ",," + gps_obj.getDatetime() + "," + (String)snifferPacket->rx_ctrl.channel + "," + (String)snifferPacket->rx_ctrl.rssi + "," + gps_obj.getLat() + "," + gps_obj.getLon() + "," + gps_obj.getAlt() + "," + gps_obj.getAccuracy() + ",WIFI"; + Serial.println(wardrive_line); + buffer_obj.append(wardrive_line); + } + } + #endif + } + } + } + } + else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_RAW_CAPTURE) { + if (type == WIFI_PKT_MGMT) { - bool mac_match = true; - for (int i = 0; i < 6; i++) { - if (snifferPacket->payload[10 + i] != target_mac[i]) { - mac_match = false; + len -= 4; + wifi_scan_obj.mgmt_frames++; + + // Do our counts + if (snifferPacket->payload[0] == 0x40) // Probe request + wifi_scan_obj.req_frames++; + else if (snifferPacket->payload[0] == 0x50) // Probe response + wifi_scan_obj.resp_frames++; + else if (snifferPacket->payload[0] == 0x80) // Beacon + wifi_scan_obj.beacon_frames++; + else if (snifferPacket->payload[0] == 0xC0) // Deauth + wifi_scan_obj.deauth_frames++; + else if (((snifferPacket->payload[30] == 0x88 && snifferPacket->payload[31] == 0x8e) || ( snifferPacket->payload[32] == 0x88 && snifferPacket->payload[33] == 0x8e))) // eapol + wifi_scan_obj.eapol_frames++; + + // Get min/max rssi + if (snifferPacket->rx_ctrl.rssi < wifi_scan_obj.min_rssi) + wifi_scan_obj.min_rssi = snifferPacket->rx_ctrl.rssi; + + if (snifferPacket->rx_ctrl.rssi > wifi_scan_obj.max_rssi) + wifi_scan_obj.max_rssi = snifferPacket->rx_ctrl.rssi; + } + else { + wifi_scan_obj.data_frames++; + } + buffer_obj.append(snifferPacket, len); + } + else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN) { + bool found = false; + uint8_t targ_index = 0; + AccessPoint targ_ap; + + // Check list of APs + for (int i = 0; i < access_points->size(); i++) { + if (access_points->get(i).selected) { + uint8_t addr[] = {snifferPacket->payload[10], + snifferPacket->payload[11], + snifferPacket->payload[12], + snifferPacket->payload[13], + snifferPacket->payload[14], + snifferPacket->payload[15]}; + // Compare AP bssid to ssid of recvd packet + for (int x = 0; x < 6; x++) { + if (addr[x] != access_points->get(i).bssid[x]) { + found = false; + break; + } + else + found = true; + } + if (found) { + targ_ap = access_points->get(i); + targ_index = i; break; } } + } + if (!found) + return; - // If MAC matches, call processPwnagotchiBeacon with frame data - if (mac_match) { - Serial.println("Pwnagotchi beacon detected!"); - wifi_scan_obj.processPwnagotchiBeacon(snifferPacket->payload, len); - return; - } + if ((targ_ap.rssi + 1 < snifferPacket->rx_ctrl.rssi) || (snifferPacket->rx_ctrl.rssi + 1 < targ_ap.rssi)) { + targ_ap.rssi = snifferPacket->rx_ctrl.rssi; + access_points->set(targ_index, targ_ap); - if (wifi_scan_obj.currentScanMode == WIFI_SCAN_PWN) { - buffer_obj.append(snifferPacket, len); - return; - } - - // Do signal strength stuff first - else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_SIG_STREN) { - bool found = false; - uint8_t targ_index = 0; - AccessPoint targ_ap; + Serial.println((String)access_points->get(targ_index).essid + " RSSI: " + (String)access_points->get(targ_index).rssi); + } + else + return; - // Check list of APs - for (int i = 0; i < access_points->size(); i++) { - if (access_points->get(i).selected) { - uint8_t addr[] = {snifferPacket->payload[10], - snifferPacket->payload[11], - snifferPacket->payload[12], - snifferPacket->payload[13], - snifferPacket->payload[14], - snifferPacket->payload[15]}; - // Compare AP bssid to ssid of recvd packet - for (int x = 0; x < 6; x++) { - if (addr[x] != access_points->get(i).bssid[x]) { - found = false; - break; + buffer_obj.append(snifferPacket, len); + } + else if (wifi_scan_obj.currentScanMode == BT_SCAN_FLOCK) { + if (type == WIFI_PKT_MGMT) { + len -= 4; + if (snifferPacket->payload[0] == 0x40) { + String probe_req_essid; + + for (int i = 0; i < snifferPacket->payload[25]; i++) + probe_req_essid.concat((char)snifferPacket->payload[26 + i]); + + Serial.println(probe_req_essid); + + + for (int i = 0; i < sizeof(flock_ssid)/sizeof(wifi_scan_obj.flock_ssid[0]); i++) { + if (strcasestr(probe_req_essid.c_str(), wifi_scan_obj.flock_ssid[i])) { + //Serial.print(F("Probe Request: ")); + //Serial.println(probe_req_essid); + + char addr[] = "00:00:00:00:00:00"; + getMAC(addr, snifferPacket->payload, 10); + #ifdef HAS_SCREEN + display_string.concat(MAGENTA_KEY); + display_string.concat((String)snifferPacket->rx_ctrl.rssi); + display_string.concat(" "); + display_string.concat(addr); + display_string.concat(" -> "); + display_string.concat(probe_req_essid); + + int temp_len = display_string.length(); + + for (int i = 0; i < 40; i++) + { + display_string.concat(" "); } - else - found = true; - } - if (found) { - targ_ap = access_points->get(i); - targ_index = i; + + //while (display_obj.printing) + // delay(1); + if (!display_obj.printing) { + display_obj.loading = true; + display_obj.display_buffer->add(display_string); + display_obj.loading = false; + } + #endif + + Serial.println(display_string); + + buffer_obj.append(snifferPacket, len); + break; + } + } + } + + else if (snifferPacket->payload[0] == 0x80) { + if (snifferPacket->payload[37] > 0) { + for (int i = 0; i < snifferPacket->payload[37]; i++) + essid.concat((char)snifferPacket->payload[i + 38]); + + Serial.println(essid); + + for (int i = 0; i < sizeof(flock_ssid)/sizeof(wifi_scan_obj.flock_ssid[0]); i++) { + if (strcasestr(essid.c_str(), wifi_scan_obj.flock_ssid[i])) { + //Serial.print(F("Beacon : ")); + //Serial.println(essid); + + char addr[] = "00:00:00:00:00:00"; + getMAC(addr, snifferPacket->payload, 10); + #ifdef HAS_SCREEN + display_string.concat(GREEN_KEY); + display_string.concat((String)snifferPacket->rx_ctrl.rssi); + display_string.concat(" "); + display_string.concat(addr); + display_string.concat(" -> "); + display_string.concat(essid); + + int temp_len = display_string.length(); + + for (int i = 0; i < 40; i++) + { + display_string.concat(" "); + } + + //while (display_obj.printing) + // delay(1); + if (!display_obj.printing) { + display_obj.loading = true; + display_obj.display_buffer->add(display_string); + display_obj.loading = false; + } + #endif + + Serial.println(display_string); + + buffer_obj.append(snifferPacket, len); break; } } } - if (!found) - return; - - if ((targ_ap.rssi + 5 < snifferPacket->rx_ctrl.rssi) || (snifferPacket->rx_ctrl.rssi + 5 < targ_ap.rssi)) { - targ_ap.rssi = snifferPacket->rx_ctrl.rssi; - access_points->set(targ_index, targ_ap); - Serial.println((String)access_points->get(targ_index).essid + " RSSI: " + (String)access_points->get(targ_index).rssi); - display_string.concat((String)access_points->get(targ_index).essid); - display_string.concat(" RSSI: "); - display_string.concat((String)access_points->get(targ_index).rssi); - int temp_len = display_string.length(); - for (int i = 0; i < 50 - temp_len; i++) - { - display_string.concat(" "); - } - #ifdef HAS_SCREEN - display_obj.display_buffer->add(display_string); - #endif - return; - } } - - else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_AP) { - 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: "); - char addr[] = "00:00:00:00:00:00"; - getMAC(addr, snifferPacket->payload, 10); - Serial.print(addr); - Serial.print(" ESSID Len: " + (String)snifferPacket->payload[37]); - Serial.print(" ESSID: "); - #ifdef HAS_FULL_SCREEN - display_string.concat(snifferPacket->rx_ctrl.rssi); - display_string.concat(" "); - display_string.concat(snifferPacket->rx_ctrl.channel); - display_string.concat(" "); - #endif - if (snifferPacket->payload[37] <= 0) - display_string.concat(addr); - else { - for (int i = 0; i < snifferPacket->payload[37]; i++) - { - Serial.print((char)snifferPacket->payload[i + 38]); - display_string.concat((char)snifferPacket->payload[i + 38]); - } - } - - int temp_len = display_string.length(); - - #ifdef HAS_SCREEN - for (int i = 0; i < 40 - temp_len; i++) - { - display_string.concat(" "); - } - - Serial.print(" "); - - display_obj.display_buffer->add(display_string); - #endif - - Serial.println(); - - buffer_obj.append(snifferPacket, len); - } - else if (wifi_scan_obj.currentScanMode == WIFI_SCAN_WAR_DRIVE) { - #ifdef HAS_GPS - if (gps_obj.getGpsModuleStatus()) { - bool do_save = false; - - // Check if we've already seen this AP - char addr[] = "00:00:00:00:00:00"; - getMAC(addr, snifferPacket->payload, 10); - if (wifi_scan_obj.seen_mac(reinterpret_cast(addr))) - return; - - Serial.print("RSSI: "); - Serial.print(snifferPacket->rx_ctrl.rssi); - Serial.print(" Ch: "); - Serial.print(snifferPacket->rx_ctrl.channel); - - if (snifferPacket->payload[37] > 0) { - Serial.print(" ESSID: "); - for (int i = 0; i < snifferPacket->payload[37]; i++) - { - Serial.print((char)snifferPacket->payload[i + 38]); - display_string.concat((char)snifferPacket->payload[i + 38]); - essid.concat((char)snifferPacket->payload[i + 38]); - } - } - else { - Serial.print(" BSSID: "); - Serial.print(addr); - display_string.concat(addr); - } - - if (gps_obj.getFixStatus()) { - do_save = true; - display_string.concat(" | Lt: " + gps_obj.getLat()); - display_string.concat(" | Ln: " + gps_obj.getLon()); - } - else - display_string.concat(" | GPS: No Fix"); - - int temp_len = display_string.length(); - - #ifdef HAS_SCREEN - for (int i = 0; i < 40 - temp_len; i++) - { - display_string.concat(" "); - } - - Serial.print(" "); - - display_obj.display_buffer->add(display_string); - #endif - - Serial.println(); - - wifi_scan_obj.save_mac(reinterpret_cast(addr)); - - int n = WiFi.scanNetworks(false, true, false, 110, wifi_scan_obj.set_channel); - - if (do_save) { - if (n > 0) { - for (int i = 0; i < n; i++) { - Serial.printf("%-32.32s", WiFi.SSID(i).c_str()); - Serial.print(" -> "); - Serial.println(wifi_scan_obj.security_int_to_string(WiFi.encryptionType(i)).c_str()); - } - } - String wardrive_line = (String)addr + "," + essid + "," + wifi_scan_obj.security_int_to_string(snifferPacket->rx_ctrl.channel) + "," + gps_obj.getDatetime() + "," + (String)snifferPacket->rx_ctrl.channel + "," + (String)snifferPacket->rx_ctrl.rssi + "," + gps_obj.getLat() + "," + gps_obj.getLon() + "," + gps_obj.getAlt() + "," + gps_obj.getAccuracy() + ",WIFI"; - Serial.println(wardrive_line); - //buffer_obj.append(wardrive_line); - } - } - #endif - } } } } @@ -6256,21 +7273,22 @@ void WiFiScan::stationSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t typ char sta_addr[] = "00:00:00:00:00:00"; if (ap_is_src) { - Serial.print("ap: "); + Serial.print(F("ap: ")); Serial.print(ap_addr); - Serial.print(" -> sta: "); + Serial.print(F(" -> sta: ")); getMAC(sta_addr, snifferPacket->payload, 4); Serial.println(sta_addr); } else { - Serial.print("sta: "); + Serial.print(F("sta: ")); getMAC(sta_addr, snifferPacket->payload, 10); Serial.print(sta_addr); - Serial.print(" -> ap: "); + Serial.print(F(" -> ap: ")); Serial.println(ap_addr); } - display_string.concat(replaceOUIWithManufacturer(sta_addr)); + //display_string.concat(replaceOUIWithManufacturer(sta_addr)); + display_string.concat(sta_addr); //display_string.concat(sta_addr); display_string.concat(" -> "); @@ -6307,7 +7325,7 @@ void WiFiScan::stationSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t typ buffer_obj.append(snifferPacket, len); } -void WiFiScan::rawSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type) +/*void WiFiScan::rawSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type) { extern WiFiScan wifi_scan_obj; @@ -6387,38 +7405,13 @@ void WiFiScan::rawSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type) access_points->set(targ_index, targ_ap); Serial.println((String)access_points->get(targ_index).essid + " RSSI: " + (String)access_points->get(targ_index).rssi); - - /*display_string.concat((String)access_points->get(targ_index).essid); - #ifndef HAS_MINI_SCREEN - display_string.concat(" RSSI: "); - display_string.concat((String)access_points->get(targ_index).rssi); - #endif - int temp_len = display_string.length(); - for (int i = 0; i < 50 - temp_len; i++) - { - display_string.concat(" "); - } - #ifdef HAS_SCREEN - display_obj.display_buffer->add(display_string); - #ifdef HAS_MINI_SCREEN - display_string = ""; - display_string.concat("RSSI: "); - display_string.concat((String)access_points->get(targ_index).rssi); - temp_len = display_string.length(); - for (int i = 0; i < 50 - temp_len; i++) - { - display_string.concat(" "); - } - display_obj.display_buffer->add(display_string); - #endif - #endif*/ } else return; } buffer_obj.append(snifferPacket, len); -} +}*/ void WiFiScan::deauthSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type) { @@ -6445,17 +7438,17 @@ void WiFiScan::deauthSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type if ((snifferPacket->payload[0] == 0xA0 || snifferPacket->payload[0] == 0xC0 ) && (buf == 0)) { delay(random(0, 10)); - Serial.print("RSSI: "); + Serial.print(F("RSSI: ")); Serial.print(snifferPacket->rx_ctrl.rssi); - Serial.print(" Ch: "); + Serial.print(F(" Ch: ")); Serial.print(snifferPacket->rx_ctrl.channel); - Serial.print(" BSSID: "); + Serial.print(F(" BSSID: ")); char addr[] = "00:00:00:00:00:00"; char dst_addr[] = "00:00:00:00:00:00"; getMAC(addr, snifferPacket->payload, 10); getMAC(dst_addr, snifferPacket->payload, 4); Serial.print(addr); - Serial.print(" -> "); + Serial.print(F(" -> ")); Serial.print(dst_addr); display_string.concat(text_table4[0]); display_string.concat(snifferPacket->rx_ctrl.rssi); @@ -6481,7 +7474,7 @@ void WiFiScan::deauthSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type } } -void WiFiScan::probeSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type) { +/*void WiFiScan::probeSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type) { extern WiFiScan wifi_scan_obj; @@ -6512,16 +7505,16 @@ void WiFiScan::probeSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type) String probe_req_essid; delay(random(0, 10)); - Serial.print("RSSI: "); + Serial.print(F("RSSI: ")); Serial.print(snifferPacket->rx_ctrl.rssi); - Serial.print(" Ch: "); + Serial.print(F(" Ch: ")); Serial.print(snifferPacket->rx_ctrl.channel); - Serial.print(" Client: "); + Serial.print(F(" Client: ")); char addr[] = "00:00:00:00:00:00"; getMAC(addr, snifferPacket->payload, 10); Serial.print(addr); display_string.concat(addr); - Serial.print(" Requesting: "); + Serial.print(F(" Requesting: ")); display_string.concat(" -> "); for (int i = 0; i < snifferPacket->payload[25]; i++) { @@ -6577,12 +7570,12 @@ void WiFiScan::probeSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type) if (wifi_scan_obj.seen_mac(reinterpret_cast(addr))) return; - Serial.print("RSSI: "); + Serial.print(F("RSSI: ")); Serial.print(snifferPacket->rx_ctrl.rssi); - Serial.print(" Ch: "); + Serial.print(F(" Ch: ")); Serial.print(snifferPacket->rx_ctrl.channel); - Serial.print(" BSSID: "); + Serial.print(F(" BSSID: ")); Serial.print(addr); display_string.concat(addr); @@ -6622,7 +7615,7 @@ void WiFiScan::probeSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type) } } } -} +}*/ void WiFiScan::beaconListSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type) { wifi_promiscuous_pkt_t *snifferPacket = (wifi_promiscuous_pkt_t*)buf; @@ -6668,16 +7661,16 @@ void WiFiScan::beaconListSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t return; delay(random(0, 10)); - Serial.print("RSSI: "); + Serial.print(F("RSSI: ")); Serial.print(snifferPacket->rx_ctrl.rssi); - Serial.print(" Ch: "); + Serial.print(F(" Ch: ")); Serial.print(snifferPacket->rx_ctrl.channel); - Serial.print(" Client: "); + Serial.print(F(" Client: ")); char addr[] = "00:00:00:00:00:00"; getMAC(addr, snifferPacket->payload, 10); Serial.print(addr); display_string.concat(addr); - Serial.print(" Requesting: "); + Serial.print(F(" Requesting: ")); display_string.concat(" -> "); // ESSID @@ -7804,7 +8797,7 @@ void WiFiScan::eapolSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type) if (( (snifferPacket->payload[30] == 0x88 && snifferPacket->payload[31] == 0x8e)|| ( snifferPacket->payload[32] == 0x88 && snifferPacket->payload[33] == 0x8e) )){ num_eapol++; - Serial.println("Received EAPOL:"); + Serial.println(F("Received EAPOL:")); char addr[] = "00:00:00:00:00:00"; getMAC(addr, snifferPacket->payload, 10); @@ -7912,7 +8905,7 @@ void WiFiScan::activeEapolSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t if (( (snifferPacket->payload[30] == 0x88 && snifferPacket->payload[31] == 0x8e)|| ( snifferPacket->payload[32] == 0x88 && snifferPacket->payload[33] == 0x8e) )){ num_eapol++; - Serial.println("Received EAPOL:"); + Serial.println(F("Received EAPOL:")); } @@ -7977,7 +8970,6 @@ bool WiFiScan::filterActive() { // Channel - button pressed if (b == 4) { if (set_channel > 1) { - Serial.println("Shit channel down"); set_channel--; delay(70); display_obj.tft.fillRect(127, 0, 193, 28, TFT_BLACK); @@ -7991,7 +8983,6 @@ bool WiFiScan::filterActive() { // Channel + button pressed else if (b == 5) { if (set_channel < MAX_CHANNEL) { - Serial.println("Shit channel up"); set_channel++; delay(70); display_obj.tft.fillRect(127, 0, 193, 28, TFT_BLACK); @@ -8002,7 +8993,6 @@ bool WiFiScan::filterActive() { } } else if (b == 6) { - Serial.println("Exiting packet monitor..."); this->StartScan(WIFI_SCAN_OFF); //display_obj.init(); this->orient_display = true; @@ -8016,7 +9006,7 @@ bool WiFiScan::filterActive() { initTime = millis(); y_pos_x = ((-num_eapol * (y_scale * 3)) + (HEIGHT_1 - 2)); // GREEN if (y_pos_x >= HEIGHT_1) { - Serial.println("Max EAPOL number reached. Adjusting..."); + Serial.println(F("Max EAPOL number reached. Adjusting...")); num_eapol = 0; } @@ -8175,7 +9165,6 @@ bool WiFiScan::filterActive() { // Channel - button pressed else if (b == 4) { if (set_channel > 1) { - Serial.println("Shit channel down"); set_channel--; delay(70); display_obj.tft.fillRect(127, 0, 193, 28, TFT_BLACK); @@ -8191,7 +9180,6 @@ bool WiFiScan::filterActive() { // Channel + button pressed else if (b == 5) { if (set_channel < MAX_CHANNEL) { - Serial.println("Shit channel up"); set_channel++; delay(70); display_obj.tft.fillRect(127, 0, 193, 28, TFT_BLACK); @@ -8204,7 +9192,6 @@ bool WiFiScan::filterActive() { } } else if (b == 6) { - Serial.println("Exiting packet monitor..."); this->StartScan(WIFI_SCAN_OFF); this->orient_display = true; return; @@ -8366,7 +9353,7 @@ void WiFiScan::channelHop(bool filtered, bool ranged) if (access_points->get(i).selected) { ap_selected = true; if (access_points->get(i).channel == this->set_channel) { - Serial.println("Setting to channel " + (String)this->set_channel + " for AP " + access_points->get(i).essid); + //Serial.println("Setting to channel " + (String)this->set_channel + " for AP " + access_points->get(i).essid); channel_match = true; break; } @@ -8458,7 +9445,7 @@ void WiFiScan::drawChannelLine() { display_obj.tft.fillRect(0, TFT_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 2), TFT_WIDTH, (CHAR_WIDTH * 2) - 1, TFT_BLACK); //#else //#endif - Serial.println("Drawing channel line..."); + //Serial.println("Drawing channel line..."); #ifndef HAS_DUAL_BAND for (int i = 1; i < CHAN_PER_PAGE + 1; i++) { int x_mult = (i * 2) - 1; @@ -8503,7 +9490,7 @@ void WiFiScan::channelActivityLoop(uint32_t tick) { if (tick - this->initTime >= BANNER_TIME * 50) { initTime = millis(); - Serial.println("--------------"); + Serial.println(F("--------------")); for (int i = (activity_page * CHAN_PER_PAGE) - CHAN_PER_PAGE; i < activity_page * CHAN_PER_PAGE; i++) { #ifndef HAS_DUAL_BAND Serial.println((String)(i+1) + ": " + (String)channel_activity[i]); @@ -8659,7 +9646,7 @@ void WiFiScan::renderRawStats() { display_obj.tft.setTextSize(1); display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK); - display_obj.tft.println("Stats\n"); + display_obj.tft.println(F("Stats\n")); display_obj.tft.println(" Mgmt: " + (String)this->mgmt_frames); display_obj.tft.println(" Data: " + (String)this->data_frames); @@ -8771,96 +9758,124 @@ bool WiFiScan::checkHostPort(IPAddress ip, uint16_t port, uint16_t timeout) { return false; } -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]); +#ifndef HAS_DUAL_BAND + 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]); - // 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; + // 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; + const ip4_addr_t* ipaddr_ret = NULL; + struct eth_addr* eth_ret = NULL; - // Use actual interface instead of NULL - if (etharp_find_addr(NULL, &test_ip, ð_ret, &ipaddr_ret) >= 0) { - return true; + // Use actual interface instead of NULL + if (etharp_find_addr(NULL, &test_ip, ð_ret, &ipaddr_ret) >= 0) { + return true; + } + + return false; } - return false; -} + bool WiFiScan::singleARP(IPAddress ip_addr) { -bool WiFiScan::singleARP(IPAddress ip_addr) { + #ifndef HAS_DUAL_BAND + 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 - #ifndef HAS_DUAL_BAND - 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, - ip_addr[0], - ip_addr[1], - ip_addr[2], - ip_addr[3]); - - etharp_request(netif_interface, &lwip_ip); - - delay(250); - - if (this->readARP(ip_addr)) - return true; - - return false; -} - -void WiFiScan::fullARP() { - String display_string = ""; - String output_line = ""; - - #ifndef HAS_DUAL_BAND - 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)) { ip4_addr_t lwip_ip; IP4_ADDR(&lwip_ip, - this->current_scan_ip[0], - this->current_scan_ip[1], - this->current_scan_ip[2], - this->current_scan_ip[3]); + ip_addr[0], + ip_addr[1], + ip_addr[2], + ip_addr[3]); etharp_request(netif_interface, &lwip_ip); - delay(100); + delay(250); - this->current_scan_ip = getNextIP(this->current_scan_ip, this->subnet); + if (this->readARP(ip_addr)) + return true; - this->arp_count++; + return false; + } - if (this->arp_count >= 10) { - delay(250); + void WiFiScan::fullARP() { + String display_string = ""; + String output_line = ""; - this->arp_count = 0; + #ifndef HAS_DUAL_BAND + 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)) { + ip4_addr_t lwip_ip; + IP4_ADDR(&lwip_ip, + this->current_scan_ip[0], + this->current_scan_ip[1], + this->current_scan_ip[2], + this->current_scan_ip[3]); + + 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) { + delay(250); + + this->arp_count = 0; + + for (int i = 10; i > 0; i--) { + IPAddress check_ip = getPrevIP(this->current_scan_ip, this->subnet, i); + display_string = ""; + output_line = ""; + if (this->readARP(check_ip)) { + ipList->add(check_ip); + output_line = check_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(" "); + } + #ifdef HAS_SCREEN + display_obj.display_buffer->add(display_string); + #endif + buffer_obj.append(output_line + "\n"); + Serial.println(output_line); + } + } + } + } + + if (this->current_scan_ip == IPAddress(0, 0, 0, 0)) { + + for (int i = this->arp_count; i > 0; i--) { + delay(250); - for (int i = 10; i > 0; i--) { IPAddress check_ip = getPrevIP(this->current_scan_ip, this->subnet, i); display_string = ""; output_line = ""; @@ -8880,42 +9895,16 @@ void WiFiScan::fullARP() { Serial.println(output_line); } } - } - } - - if (this->current_scan_ip == IPAddress(0, 0, 0, 0)) { - - for (int i = this->arp_count; i > 0; i--) { - delay(250); - - IPAddress check_ip = getPrevIP(this->current_scan_ip, this->subnet, i); - display_string = ""; - output_line = ""; - if (this->readARP(check_ip)) { - ipList->add(check_ip); - output_line = check_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(" "); - } + this->arp_count = 0; + if (!this->scan_complete) { + this->scan_complete = true; #ifdef HAS_SCREEN - display_obj.display_buffer->add(display_string); + display_obj.display_buffer->add("Scan complete"); #endif - buffer_obj.append(output_line + "\n"); - Serial.println(output_line); } } - this->arp_count = 0; - if (!this->scan_complete) { - this->scan_complete = true; - #ifdef HAS_SCREEN - display_obj.display_buffer->add("Scan complete"); - #endif - } } -} +#endif void WiFiScan::pingScan(uint8_t scan_mode) { String display_string = ""; @@ -8988,50 +9977,6 @@ void WiFiScan::pingScan(uint8_t scan_mode) { } } } - - /*else if (scan_mode == WIFI_SCAN_SSH) { - if (this->current_scan_ip != IPAddress(0, 0, 0, 0)) { - this->current_scan_ip = getNextIP(this->current_scan_ip, this->subnet); - #ifndef HAS_DUAL_BAND - 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, 22); - } - } - else { - if (!this->scan_complete) { - this->scan_complete = true; - #ifdef HAS_SCREEN - display_obj.display_buffer->add("Scan complete"); - #endif - } - } - } - - else if (scan_mode == WIFI_SCAN_TELNET) { - if (this->current_scan_ip != IPAddress(0, 0, 0, 0)) { - this->current_scan_ip = getNextIP(this->current_scan_ip, this->subnet); - #ifndef HAS_DUAL_BAND - 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, 23); - } - } - else { - if (!this->scan_complete) { - this->scan_complete = true; - #ifdef HAS_SCREEN - display_obj.display_buffer->add("Scan complete"); - #endif - } - } - }*/ } void WiFiScan::portScan(uint8_t scan_mode, uint16_t targ_port) { @@ -9040,7 +9985,7 @@ void WiFiScan::portScan(uint8_t scan_mode, uint16_t targ_port) { if (this->current_scan_port < MAX_PORT) { this->current_scan_port = getNextPort(this->current_scan_port); if (this->current_scan_port % 1000 == 0) { - Serial.print("Checking IP: "); + Serial.print(F("Checking IP: ")); Serial.print(this->current_scan_ip); Serial.print(" Port: "); Serial.println(this->current_scan_port); @@ -9117,21 +10062,31 @@ void WiFiScan::main(uint32_t currentTime) (currentScanMode == BT_SCAN_WAR_DRIVE_CONT) || (currentScanMode == BT_SCAN_FLIPPER) || (currentScanMode == BT_SCAN_AIRTAG)) { - if (currentTime - initTime >= 5000) { + if (currentTime - initTime >= this->channel_hop_delay * HOP_DELAY) { initTime = millis(); #ifdef HAS_BT - pBLEScan->stop(); - delay(5); - pBLEScan->clearResults(); - pBLEScan->start(0, scanCompleteCB, false); + if (this->ble_scanning) { + pBLEScan->stop(); + pBLEScan->clearResults(); + this->ble_scanning = false; + } + else { + pBLEScan->start(0, scanCompleteCB, false); + this->ble_scanning = true; + return; + } #endif + if (currentScanMode == BT_SCAN_FLOCK) + channelHop(); } } else if (currentScanMode == WIFI_PING_SCAN) { this->pingScan(); } else if (currentScanMode == WIFI_ARP_SCAN) { - this->fullARP(); + #ifndef HAS_DUAL_BAND + this->fullARP(); + #endif } else if (currentScanMode == WIFI_PORT_SCAN_ALL) { this->portScan(WIFI_PORT_SCAN_ALL); @@ -9338,7 +10293,8 @@ void WiFiScan::main(uint32_t currentTime) #endif #endif } - else if (currentScanMode == WIFI_SCAN_EAPOL) + else if ((currentScanMode == WIFI_SCAN_EAPOL) || + (currentScanMode == WIFI_SCAN_ACTIVE_EAPOL)) { #ifdef HAS_SCREEN #ifdef HAS_ILI9341 @@ -9346,12 +10302,12 @@ void WiFiScan::main(uint32_t currentTime) #endif #endif } - else if (currentScanMode == WIFI_SCAN_ACTIVE_EAPOL) + /*else if (currentScanMode == WIFI_SCAN_ACTIVE_EAPOL) { #ifdef HAS_SCREEN eapolMonitorMain(currentTime); #endif - } + }*/ else if (currentScanMode == WIFI_SCAN_ACTIVE_LIST_EAPOL) { if (currentTime - initTime >= 1000) { initTime = millis(); @@ -9361,7 +10317,7 @@ void WiFiScan::main(uint32_t currentTime) eapolMonitorMain(currentTime); #endif } - else if ((currentScanMode == BT_SCAN_SIMPLE) || (currentScanMode == BT_SCAN_SIMPLE_TWO)) { + /*else if ((currentScanMode == BT_SCAN_SIMPLE) || (currentScanMode == BT_SCAN_SIMPLE_TWO)) { if (currentTime - initTime >= 1000) { initTime = millis(); String displayString = "BT Frames: "; @@ -9371,7 +10327,7 @@ void WiFiScan::main(uint32_t currentTime) display_obj.showCenterText(displayString, TFT_HEIGHT / 2); #endif } - } + }*/ else if (currentScanMode == WIFI_ATTACK_AUTH) { for (int i = 0; i < 55; i++) this->sendProbeAttack(currentTime); @@ -9434,25 +10390,34 @@ void WiFiScan::main(uint32_t currentTime) } } else if (currentScanMode == WIFI_ATTACK_DEAUTH) { - for (int i = 0; i < 55; i++) + for (int i = 0; i < 55; i++) { this->sendDeauthAttack(currentTime, this->dst_mac); + } if (currentTime - initTime >= 1000) { initTime = millis(); - String displayString = ""; - String displayString2 = ""; - displayString.concat(text18); - displayString.concat(packets_sent); - for (int x = 0; x < STANDARD_FONT_CHAR_LIMIT; x++) - displayString2.concat(" "); - #ifdef HAS_SCREEN - display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK); - display_obj.showCenterText(displayString2, TFT_HEIGHT / 2); - display_obj.showCenterText(displayString, TFT_HEIGHT / 2); - #endif + + char displayString[64]; // adjust size as needed + + snprintf(displayString, sizeof(displayString), "%s%u", + text18, static_cast(packets_sent)); + + char displayString2[STANDARD_FONT_CHAR_LIMIT + 1]; + for (int x = 0; x < STANDARD_FONT_CHAR_LIMIT; x++) { + displayString2[x] = ' '; + } + displayString2[STANDARD_FONT_CHAR_LIMIT] = '\0'; + + #ifdef HAS_SCREEN + display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK); + display_obj.showCenterText(displayString2, TFT_HEIGHT / 2); + display_obj.showCenterText(displayString, TFT_HEIGHT / 2); + #endif + packets_sent = 0; } } + else if (currentScanMode == WIFI_ATTACK_DEAUTH_MANUAL) { for (int i = 0; i < 55; i++) this->sendDeauthFrame(this->src_mac, this->set_channel, this->dst_mac); diff --git a/esp32_marauder/WiFiScan.h b/esp32_marauder/WiFiScan.h index 16afa12..209e469 100644 --- a/esp32_marauder/WiFiScan.h +++ b/esp32_marauder/WiFiScan.h @@ -28,12 +28,14 @@ #include "esp_wifi.h" #include "esp_wifi_types.h" #include -#include -#include +#ifndef HAS_DUAL_BAND + #include + #include +#endif #ifdef HAS_DUAL_BAND #include "esp_system.h" #endif -#ifdef HAS_BT +#if defined(HAS_BT) && !defined(HAS_DUAL_BAND) #include "esp_bt.h" #endif #ifdef HAS_SCREEN @@ -523,6 +525,8 @@ class WiFiScan NimBLEAdvertisementData GetUniversalAdvertisementData(EBLEPayloadType type); #endif + void showNetworkInfo(); + void setNetworkInfo(); void fullARP(); bool readARP(IPAddress targ_ip); bool singleARP(IPAddress ip_addr); @@ -590,7 +594,6 @@ class WiFiScan void RunBluetoothScan(uint8_t scan_mode, uint16_t color); void RunSourApple(uint8_t scan_mode, uint16_t color); void RunSwiftpairSpam(uint8_t scan_mode, uint16_t color); - void RunLvJoinWiFi(uint8_t scan_mode, uint16_t color); void RunEvilPortal(uint8_t scan_mode, uint16_t color); void RunPingScan(uint8_t scan_mode, uint16_t color); void RunPortScanAll(uint8_t scan_mode, uint16_t color); @@ -624,6 +627,14 @@ class WiFiScan bool force_probe = false; bool save_pcap = false; bool ep_deauth = false; + bool ble_scanning = false; + + char* flock_ssid[4] = { + "flock", + "penguin", + "pigvision", + "fs ext battery" + }; #ifdef HAS_DUAL_BAND uint8_t channel_activity[DUAL_BAND_CHANNELS] = {}; @@ -787,12 +798,12 @@ class WiFiScan static void getMAC(char *addr, uint8_t* data, uint16_t offset); static void pwnSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type); static void beaconSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type); - static void rawSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type); + //static void rawSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type); static void stationSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type); static void apSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type); static void apSnifferCallbackFull(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); + //static void probeSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type); static void beaconListSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type); static void activeEapolSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type); static void eapolSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type); diff --git a/esp32_marauder/configs.h b/esp32_marauder/configs.h index 6dcf0ee..790b455 100644 --- a/esp32_marauder/configs.h +++ b/esp32_marauder/configs.h @@ -32,7 +32,7 @@ //#define MARAUDER_V8 //// END BOARD TARGETS - #define MARAUDER_VERSION "v1.8.11" + #define MARAUDER_VERSION "v1.9.0" #define GRAPH_REFRESH 100 @@ -407,7 +407,7 @@ //#define HAS_FLIPPER_LED //#define FLIPPER_ZERO_HAT //#define HAS_BATTERY - //#define HAS_BT + #define HAS_BT //#define HAS_BUTTONS #define HAS_NEOPIXEL_LED //#define HAS_PWR_MGMT @@ -426,9 +426,9 @@ //#define HAS_FLIPPER_LED //#define FLIPPER_ZERO_HAT #define HAS_BATTERY - //#define HAS_BT + #define HAS_BT //#define HAS_BUTTONS - #define HAS_NEOPIXEL_LED + //#define HAS_NEOPIXEL_LED //#define HAS_PWR_MGMT #define HAS_SCREEN #define HAS_FULL_SCREEN diff --git a/esp32_marauder/esp32_marauder.ino b/esp32_marauder/esp32_marauder.ino index a6fd2ac..4e51ed7 100644 --- a/esp32_marauder/esp32_marauder.ino +++ b/esp32_marauder/esp32_marauder.ino @@ -298,6 +298,16 @@ void setup() menu_function_obj.RunSetup(); #endif + /*char ssidBuf[64] = {0}; // or prefill with existing SSID + if (keyboardInput(ssidBuf, sizeof(ssidBuf), "Enter SSID")) { + // user pressed OK + Serial.println(ssidBuf); + } else { + Serial.println(F("User exited keyboard")); + } + + menu_function_obj.changeMenu(menu_function_obj.current_menu);*/ + wifi_scan_obj.StartScan(WIFI_SCAN_OFF); Serial.println(F("CLI Ready")); diff --git a/esp32_marauder/utils.h b/esp32_marauder/utils.h index cfa9ea0..d293e1a 100644 --- a/esp32_marauder/utils.h +++ b/esp32_marauder/utils.h @@ -8,7 +8,7 @@ #include "configs.h" -#include "esp_heap_caps.h" +//#include "esp_heap_caps.h" struct mac_addr { unsigned char bytes[6]; @@ -27,7 +27,7 @@ struct ProbeReqSsid { uint8_t requests; }; -const char apple_ouis[][9] PROGMEM = { +/*const char apple_ouis[][9] PROGMEM = { "00:17:F2", "00:1E:C2", "00:26:08", "F8:1E:DF", "BC:92:6B", "28:E0:2C", "3C:07:54", "7C:D1:C3", "DC:A9:04", "F0:D1:A9", "C0:2C:5C", "00:03:93", "00:03:94", "00:03:95", "00:03:96", @@ -114,14 +114,7 @@ const char linksys_ouis[][9] PROGMEM = { }; const char netgear_ouis[][9] PROGMEM = { - "00:09:5B", "00:0F:B5", "00:14:6C", "00:1B:2F", "00:1E:2A", "00:1F:33", "00:22:3F", "00:22:4B", "00:26:F2", - "00:8E:F2", "08:02:8E", "08:36:C9", "08:BD:43", "10:0C:6B", "10:0D:7F", "10:DA:43", "14:59:C0", "20:4E:7F", - "20:E5:2A", "28:80:88", "28:94:01", "28:C6:8E", "2C:30:33", "2C:B0:5D", "30:46:9A", "34:98:B5", "38:94:ED", - "3C:37:86", "40:5D:82", "44:A5:6E", "4C:60:DE", "50:4A:6E", "50:6A:03", "54:07:7D", "58:EF:68", "60:38:E0", - "6C:B0:CE", "6C:CD:D6", "74:44:01", "80:37:73", "84:1B:5E", "8C:3B:AD", "94:18:65", "9C:3D:CF", "9C:C9:EB", - "9C:D3:6D", "A0:04:60", "A0:21:B7", "A0:40:A0", "A4:2B:8C", "B0:39:56", "B0:7F:B9", "B0:B9:8A", "BC:A5:11", - "C0:3F:0E", "C0:FF:D4", "C4:04:15", "C4:3D:C7", "C8:9E:43", "CC:40:D0", "DC:EF:09", "E0:46:9A", "E0:46:EE", - "E0:91:F5", "E4:F4:C6", "E8:FC:AF", "F8:73:94" + "00:09:5B", "00:0F:B5", "00:14:6C" }; const char oneplus_ouis[][9] PROGMEM = { @@ -154,7 +147,7 @@ const char tplink_ouis[][9] PROGMEM = { const char xiaomi_ouis[][9] PROGMEM = { "04:CF:8C", "18:59:36", "38:1A:2D", "64:B4:73", "78:02:F8", "90:4E:91", "C4:0B:CB", "D0:DB:32" -}; +};*/ uint8_t getDRAMUsagePercent() { //size_t total = heap_caps_get_total_size(MALLOC_CAP_8BIT); @@ -171,7 +164,7 @@ uint8_t getDRAMUsagePercent() { #ifdef HAS_PSRAM uint8_t getPSRAMUsagePercent() { - //size_t total = heap_caps_get_total_size(MALLOC_CAP_SPIRAM); + /*//size_t total = heap_caps_get_total_size(MALLOC_CAP_SPIRAM); //size_t free = heap_caps_get_free_size(MALLOC_CAP_SPIRAM); size_t total = ESP.getPsramSize(); @@ -181,7 +174,8 @@ uint8_t getDRAMUsagePercent() { size_t used = total - free; uint8_t percent = (used * 100) / total; - return percent; + return percent;*/ + return getDRAMUsagePercent(); } #endif @@ -299,7 +293,7 @@ void convertMacStringToUint8(const String& macStr, uint8_t macAddr[6]) { } // Function to check if the given MAC address matches any known OUI -const char* getManufacturer(const char *addr) { +/*const char* getManufacturer(const char *addr) { static char oui[9]; // Temporary buffer for extracted OUI // Extract the first three bytes (OUI) from addr @@ -316,7 +310,7 @@ const char* getManufacturer(const char *addr) { for (uint8_t i = 0; i < sizeof(list) / sizeof(list[0]); i++) { \ char storedOUI[9]; \ strcpy_P(storedOUI, list[i]); \ - /* Convert the stored OUI to lowercase */ \ + \ for (int j = 0; j < 8; j++) { \ storedOUI[j] = tolower(storedOUI[j]); \ } \ @@ -355,7 +349,7 @@ String replaceOUIWithManufacturer(const char *sta_addr) { // Construct the new address: manufacturer + the remaining MAC address (after the first 3 bytes) return String(manufacturer) + mac_suffix; -} +}*/ IPAddress getNextIP(IPAddress currentIP, IPAddress subnetMask) { // Convert IPAddress to uint32_t