handshake-capture-c6: production SD gating (SD_IsReady), v1.0.1

- Gate capture on SD_IsReady() after successful SD_Init; avoid false
  'insert SD' when SD.cardType() lies after WiFi on shared SPI with LCD
- SD_Init: LCD CS high, SD.end() on empty card; HandshakeCapture save path
  retries SD_Init before discard
- FAT filename sanitize, discard deadlocks, WPA3 scan labels, docs (README,
  PRODUCTION, IMPROVEMENTS), firmware version 1.0.1

Made-with: Cursor
This commit is contained in:
drjones
2026-03-21 01:12:12 -07:00
parent 4bef28bd83
commit 804e71e175
11 changed files with 512 additions and 153 deletions

View File

@@ -1,6 +1,6 @@
/*
* WiFi Handshake Capture - ESP32-C6 1.47" LCD
* Multi-target capture: up to 3 networks per channel.
* Multi-target capture: up to 2 networks per channel (deauth + wait, rotate until all done).
* Green = pending, orange blink = active target, red = captured.
*/
@@ -12,13 +12,13 @@
enum CaptureState {
STATE_SCANNING,
STATE_CAPTURING,
STATE_WAITING
STATE_CAPTURING
};
CaptureState captureState = STATE_SCANNING;
unsigned long capture_start_time = 0;
const unsigned long CHANNEL_TIMEOUT_MS = 50000; // ~3 cycles (observe+deauth+capture)
// Hard cap per channel visit: should exceed MAX_OBSERVE_CYCLES * (observe + capture).
const unsigned long CHANNEL_TIMEOUT_MS = 150000UL;
// ─── Live capture visual update ───
@@ -69,8 +69,8 @@ void updateCaptureVisuals() {
snprintf(buf, sizeof(buf), LV_SYMBOL_CHARGE " %s +%dc",
slot->ssid, slot->client_count);
} else {
snprintf(buf, sizeof(buf), LV_SYMBOL_CHARGE " %s %d/2",
slot->ssid, slot->eapol_count);
snprintf(buf, sizeof(buf), LV_SYMBOL_CHARGE " %s %d/%d",
slot->ssid, (int)slot->eapol_count, (int)HANDSHAKE_EAPOL_FRAMES);
}
Ui_SetNetworkText(i, buf);
@@ -92,13 +92,19 @@ void updateCaptureVisuals() {
last_phase = capturePhase;
}
static int last_eapol = -1;
if (capturePhase == PHASE_CAPTURING && latest_eapol_count != last_eapol) {
char ebuf[32];
snprintf(ebuf, sizeof(ebuf), "Ch %d " LV_SYMBOL_CHARGE " EAPOL %d",
current_channel, latest_eapol_count);
static uint32_t last_eapol_sig = 0xffffffffu;
uint32_t sig = 0;
for (int s = 0; s < MAX_SLOTS; s++)
sig |= (uint32_t)latest_eapol_count[s] << (8 * s);
if (capturePhase == PHASE_CAPTURING && sig != last_eapol_sig) {
char ebuf[48];
int p = snprintf(ebuf, sizeof(ebuf), "Ch%d " LV_SYMBOL_CHARGE " E", current_channel);
for (int s = 0; s < MAX_SLOTS && p < (int)sizeof(ebuf) - 6; s++) {
p += snprintf(ebuf + p, sizeof(ebuf) - (size_t)p, "%s%d",
s ? "/" : "", (int)latest_eapol_count[s]);
}
Ui_SetWifiStatus(ebuf);
last_eapol = latest_eapol_count;
last_eapol_sig = sig;
}
}
@@ -106,6 +112,9 @@ void updateCaptureVisuals() {
void setup() {
Serial.begin(115200);
delay(200);
Serial.printf("handshake-capture-c6 v%s\n", HANDSHAKE_FIRMWARE_VERSION);
LCD_Init();
Set_Backlight(100);
Lvgl_Init();
@@ -137,6 +146,14 @@ void loop() {
delay(500);
break;
}
if (!SD_IsReady()) {
SD_Init();
if (!SD_IsReady()) {
Ui_SetWifiStatus("Insert SD card");
delay(800);
break;
}
}
startMultiCapture();
if (is_capturing) {
captureState = STATE_CAPTURING;
@@ -177,9 +194,6 @@ void loop() {
}
break;
}
case STATE_WAITING:
break;
}
delay(16);