feat(update): SD-card firmware update + X3 bootloader compatibility (#1786)

This commit is contained in:
eunchurn
2026-05-04 19:51:20 -04:00
committed by GitHub
parent b8a6b58b5e
commit 5717374e4b
13 changed files with 928 additions and 18 deletions
+25 -1
View File
@@ -24,6 +24,7 @@
#include "RecentBooksStore.h"
#include "activities/Activity.h"
#include "activities/ActivityManager.h"
#include "activities/settings/SdFirmwareUpdateActivity.h"
#include "components/UITheme.h"
#include "fontIds.h"
#include "util/ButtonNavigator.h"
@@ -284,6 +285,25 @@ void setup() {
break;
}
// Recovery firmware mode: hold left side button (BTN_UP) together with the power button at
// boot to skip directly to the SD-card firmware update screen. Useful on devices where USB
// flashing has been locked down (e.g. recent X3 firmware).
bool recoveryFirmwareMode = false;
if (wakeupReason == HalGPIO::WakeupReason::PowerButton) {
// Refresh the cached button state a few times — isPressed() needs ~half a second to settle
// after boot per the HalGPIO contract. Use a millis-based deadline so we always wait the full
// settle window even if the loop body takes longer than expected on slow boots.
const unsigned long settleStart = millis();
while (millis() - settleStart < 500) {
gpio.update();
delay(10);
}
if (gpio.isPressed(HalGPIO::BTN_UP)) {
recoveryFirmwareMode = true;
LOG_INF("MAIN", "Recovery firmware mode (UP + POWER held at boot)");
}
}
// First serial output only here to avoid timing inconsistencies for power button press duration verification
LOG_DBG("MAIN", "Starting CrossPoint version " CROSSPOINT_VERSION);
@@ -294,7 +314,11 @@ void setup() {
APP_STATE.loadFromFile();
RECENT_BOOKS.loadFromFile();
if (HalSystem::isRebootFromPanic()) {
if (recoveryFirmwareMode) {
// Skip normal home/reader routing: jump straight into the SD firmware picker.
activityManager.replaceActivity(
std::make_unique<SdFirmwareUpdateActivity>(renderer, mappedInputManager, /*recoveryMode=*/true));
} else if (HalSystem::isRebootFromPanic()) {
// If we rebooted from a panic, go to crash report screen to show the panic info
activityManager.goToCrashReport();
} else if (APP_STATE.openEpubPath.empty() || !APP_STATE.lastSleepFromReader ||