fix: guard Serial input calls when USB not connected at boot
Fixes device hanging when booted without USB connected. The root cause was calling Serial.available() and Serial.read() in checkForFlashCommand() when Serial.begin() was never called (USB not connected at boot). Changes: - Add if (!Serial) return guard to checkForFlashCommand() - Restore upstream while (!Serial) wait loop with 3s timeout - Remove Serial.setTxTimeoutMs(0) (not in upstream, may cause issues) - Remove unnecessary if (Serial) guards from EpubReaderActivity.cpp (Serial.printf is safe without guards, only input calls need them) Key insight: Serial.printf() is safe without guards (returns 0 when not initialized), but Serial.available()/Serial.read() cause undefined behavior on ESP32-C3 USB CDC when called without Serial.begin(). See: claude_notes/usb-serial-blocking-fix-2026-01-28.md
This commit is contained in:
@@ -127,9 +127,8 @@ void EpubReaderActivity::onEnter() {
|
||||
nextPageNumber = pageNumber;
|
||||
hasContentOffset = true;
|
||||
|
||||
if (Serial)
|
||||
Serial.printf("[%lu] [ERS] Loaded progress v1: spine %d, page %d, offset %u\n", millis(), currentSpineIndex,
|
||||
nextPageNumber, savedContentOffset);
|
||||
Serial.printf("[%lu] [ERS] Loaded progress v1: spine %d, page %d, offset %u\n", millis(), currentSpineIndex,
|
||||
nextPageNumber, savedContentOffset);
|
||||
} else {
|
||||
// Unknown version, try legacy format
|
||||
f.seek(0);
|
||||
@@ -138,9 +137,8 @@ void EpubReaderActivity::onEnter() {
|
||||
currentSpineIndex = data[0] + (data[1] << 8);
|
||||
nextPageNumber = data[2] + (data[3] << 8);
|
||||
hasContentOffset = false;
|
||||
if (Serial)
|
||||
Serial.printf("[%lu] [ERS] Loaded legacy progress (unknown version %d): spine %d, page %d\n", millis(),
|
||||
version, currentSpineIndex, nextPageNumber);
|
||||
Serial.printf("[%lu] [ERS] Loaded legacy progress (unknown version %d): spine %d, page %d\n", millis(),
|
||||
version, currentSpineIndex, nextPageNumber);
|
||||
}
|
||||
}
|
||||
} else if (fileSize >= 4) {
|
||||
@@ -150,9 +148,8 @@ void EpubReaderActivity::onEnter() {
|
||||
currentSpineIndex = data[0] + (data[1] << 8);
|
||||
nextPageNumber = data[2] + (data[3] << 8);
|
||||
hasContentOffset = false;
|
||||
if (Serial)
|
||||
Serial.printf("[%lu] [ERS] Loaded legacy progress: spine %d, page %d\n", millis(), currentSpineIndex,
|
||||
nextPageNumber);
|
||||
Serial.printf("[%lu] [ERS] Loaded legacy progress: spine %d, page %d\n", millis(), currentSpineIndex,
|
||||
nextPageNumber);
|
||||
}
|
||||
}
|
||||
f.close();
|
||||
@@ -164,9 +161,8 @@ void EpubReaderActivity::onEnter() {
|
||||
int textSpineIndex = epub->getSpineIndexForTextReference();
|
||||
if (textSpineIndex != 0) {
|
||||
currentSpineIndex = textSpineIndex;
|
||||
if (Serial)
|
||||
Serial.printf("[%lu] [ERS] Opened for first time, navigating to text reference at index %d\n", millis(),
|
||||
textSpineIndex);
|
||||
Serial.printf("[%lu] [ERS] Opened for first time, navigating to text reference at index %d\n", millis(),
|
||||
textSpineIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -639,8 +635,7 @@ void EpubReaderActivity::renderScreen() {
|
||||
|
||||
if (!section) {
|
||||
const auto filepath = epub->getSpineItem(currentSpineIndex).href;
|
||||
if (Serial)
|
||||
Serial.printf("[%lu] [ERS] Loading file: %s, index: %d\n", millis(), filepath.c_str(), currentSpineIndex);
|
||||
Serial.printf("[%lu] [ERS] Loading file: %s, index: %d\n", millis(), filepath.c_str(), currentSpineIndex);
|
||||
section = std::unique_ptr<Section>(new Section(epub, currentSpineIndex, renderer));
|
||||
|
||||
const uint16_t viewportWidth = renderer.getScreenWidth() - orientedMarginLeft - orientedMarginRight;
|
||||
@@ -651,7 +646,7 @@ void EpubReaderActivity::renderScreen() {
|
||||
if (!section->loadSectionFile(SETTINGS.getReaderFontId(), SETTINGS.getReaderLineCompression(),
|
||||
SETTINGS.extraParagraphSpacing, SETTINGS.paragraphAlignment, viewportWidth,
|
||||
viewportHeight, SETTINGS.hyphenationEnabled)) {
|
||||
if (Serial) Serial.printf("[%lu] [ERS] Cache not found, building...\n", millis());
|
||||
Serial.printf("[%lu] [ERS] Cache not found, building...\n", millis());
|
||||
sectionWasReIndexed = true;
|
||||
|
||||
// Progress bar dimensions
|
||||
@@ -697,12 +692,12 @@ void EpubReaderActivity::renderScreen() {
|
||||
if (!section->createSectionFile(SETTINGS.getReaderFontId(), SETTINGS.getReaderLineCompression(),
|
||||
SETTINGS.extraParagraphSpacing, SETTINGS.paragraphAlignment, viewportWidth,
|
||||
viewportHeight, SETTINGS.hyphenationEnabled, progressSetup, progressCallback)) {
|
||||
if (Serial) Serial.printf("[%lu] [ERS] Failed to persist page data to SD\n", millis());
|
||||
Serial.printf("[%lu] [ERS] Failed to persist page data to SD\n", millis());
|
||||
section.reset();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (Serial) Serial.printf("[%lu] [ERS] Cache found, skipping build...\n", millis());
|
||||
Serial.printf("[%lu] [ERS] Cache found, skipping build...\n", millis());
|
||||
}
|
||||
|
||||
// Determine the correct page to display
|
||||
@@ -714,9 +709,8 @@ void EpubReaderActivity::renderScreen() {
|
||||
// Use the offset to find the correct page
|
||||
const int restoredPage = section->findPageForContentOffset(savedContentOffset);
|
||||
section->currentPage = restoredPage;
|
||||
if (Serial)
|
||||
Serial.printf("[%lu] [ERS] Restored position via offset: %u -> page %d (was page %d)\n", millis(),
|
||||
savedContentOffset, restoredPage, nextPageNumber);
|
||||
Serial.printf("[%lu] [ERS] Restored position via offset: %u -> page %d (was page %d)\n", millis(),
|
||||
savedContentOffset, restoredPage, nextPageNumber);
|
||||
// Clear the offset flag since we've used it
|
||||
hasContentOffset = false;
|
||||
} else {
|
||||
@@ -728,7 +722,7 @@ void EpubReaderActivity::renderScreen() {
|
||||
renderer.clearScreen();
|
||||
|
||||
if (section->pageCount == 0) {
|
||||
if (Serial) Serial.printf("[%lu] [ERS] No pages to render\n", millis());
|
||||
Serial.printf("[%lu] [ERS] No pages to render\n", millis());
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 300, "Empty chapter", true, EpdFontFamily::BOLD);
|
||||
renderStatusBar(orientedMarginRight, orientedMarginBottom, orientedMarginLeft);
|
||||
renderer.displayBuffer();
|
||||
@@ -736,9 +730,8 @@ void EpubReaderActivity::renderScreen() {
|
||||
}
|
||||
|
||||
if (section->currentPage < 0 || section->currentPage >= section->pageCount) {
|
||||
if (Serial)
|
||||
Serial.printf("[%lu] [ERS] Page out of bounds: %d (max %d)\n", millis(), section->currentPage,
|
||||
section->pageCount);
|
||||
Serial.printf("[%lu] [ERS] Page out of bounds: %d (max %d)\n", millis(), section->currentPage,
|
||||
section->pageCount);
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 300, "Out of bounds", true, EpdFontFamily::BOLD);
|
||||
renderStatusBar(orientedMarginRight, orientedMarginBottom, orientedMarginLeft);
|
||||
renderer.displayBuffer();
|
||||
@@ -748,7 +741,7 @@ void EpubReaderActivity::renderScreen() {
|
||||
{
|
||||
auto p = section->loadPageFromSectionFile();
|
||||
if (!p) {
|
||||
if (Serial) Serial.printf("[%lu] [ERS] Failed to load page from SD - clearing section cache\n", millis());
|
||||
Serial.printf("[%lu] [ERS] Failed to load page from SD - clearing section cache\n", millis());
|
||||
section->clearCache();
|
||||
section.reset();
|
||||
return renderScreen();
|
||||
@@ -756,7 +749,7 @@ void EpubReaderActivity::renderScreen() {
|
||||
|
||||
// Handle empty pages (e.g., from malformed chapters that couldn't be parsed)
|
||||
if (p->elements.empty()) {
|
||||
if (Serial) Serial.printf("[%lu] [ERS] Page has no content (possibly malformed chapter)\n", millis());
|
||||
Serial.printf("[%lu] [ERS] Page has no content (possibly malformed chapter)\n", millis());
|
||||
renderer.drawCenteredText(UI_12_FONT_ID, 280, "Chapter content unavailable", true, EpdFontFamily::BOLD);
|
||||
renderer.drawCenteredText(UI_10_FONT_ID, 320, "(File may be malformed)");
|
||||
renderStatusBar(orientedMarginRight, orientedMarginBottom, orientedMarginLeft);
|
||||
@@ -766,7 +759,7 @@ void EpubReaderActivity::renderScreen() {
|
||||
|
||||
const auto start = millis();
|
||||
renderContents(std::move(p), orientedMarginTop, orientedMarginRight, orientedMarginBottom, orientedMarginLeft);
|
||||
if (Serial) Serial.printf("[%lu] [ERS] Rendered page in %dms\n", millis(), millis() - start);
|
||||
Serial.printf("[%lu] [ERS] Rendered page in %dms\n", millis(), millis() - start);
|
||||
}
|
||||
|
||||
// Save progress with content offset for position restoration after re-indexing
|
||||
@@ -782,9 +775,8 @@ void EpubReaderActivity::renderScreen() {
|
||||
serialization::writePod(f, contentOffset);
|
||||
|
||||
f.close();
|
||||
if (Serial)
|
||||
Serial.printf("[%lu] [ERS] Saved progress: spine %d, page %d, offset %u\n", millis(), currentSpineIndex,
|
||||
section->currentPage, contentOffset);
|
||||
Serial.printf("[%lu] [ERS] Saved progress: spine %d, page %d, offset %u\n", millis(), currentSpineIndex,
|
||||
section->currentPage, contentOffset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user