From e9120888fa8b0b454a1573765da6bcbf9c1d064d Mon Sep 17 00:00:00 2001 From: Zach Nelson Date: Mon, 25 May 2026 15:26:54 -0500 Subject: [PATCH] refactor: Drop FsFile alias, use HalFile in downstream code (#2141) --- .skills/SKILL.md | 9 +++--- lib/EpdFont/SdCardFont.cpp | 12 ++++---- lib/EpdFont/SdCardFontRegistry.cpp | 8 +++--- lib/Epub/Epub.cpp | 24 ++++++++-------- lib/Epub/Epub/BookMetadataCache.cpp | 8 +++--- lib/Epub/Epub/BookMetadataCache.h | 14 +++++----- lib/Epub/Epub/Page.cpp | 16 +++++------ lib/Epub/Epub/Page.h | 18 ++++++------ lib/Epub/Epub/Section.cpp | 10 +++---- lib/Epub/Epub/Section.h | 2 +- lib/Epub/Epub/blocks/ImageBlock.cpp | 8 +++--- lib/Epub/Epub/blocks/ImageBlock.h | 4 +-- lib/Epub/Epub/blocks/TextBlock.cpp | 4 +-- lib/Epub/Epub/blocks/TextBlock.h | 4 +-- .../converters/JpegToFramebufferConverter.cpp | 12 ++++---- lib/Epub/Epub/converters/PixelCache.h | 2 +- .../converters/PngToFramebufferConverter.cpp | 12 ++++---- lib/Epub/Epub/css/CssParser.cpp | 6 ++-- lib/Epub/Epub/css/CssParser.h | 2 +- .../Epub/parsers/ChapterHtmlSlimParser.cpp | 4 +-- lib/Epub/Epub/parsers/ContentOpfParser.h | 2 +- lib/GfxRenderer/Bitmap.cpp | 4 +-- lib/GfxRenderer/Bitmap.h | 8 +++--- lib/InflateReader/InflateReader.h | 2 +- lib/JpegToBmpConverter/JpegToBmpConverter.cpp | 16 +++++------ lib/JpegToBmpConverter/JpegToBmpConverter.h | 9 +++--- lib/KOReaderSync/KOReaderCredentialStore.cpp | 2 +- lib/KOReaderSync/KOReaderDocumentId.cpp | 2 +- lib/PngToBmpConverter/PngToBmpConverter.cpp | 12 ++++---- lib/PngToBmpConverter/PngToBmpConverter.h | 10 +++---- lib/Serialization/Serialization.h | 8 +++--- lib/Txt/Txt.cpp | 8 +++--- lib/Xtc/Xtc.cpp | 6 ++-- lib/Xtc/Xtc/XtcParser.cpp | 2 +- lib/Xtc/Xtc/XtcParser.h | 2 +- lib/ZipFile/ZipFile.cpp | 2 +- lib/ZipFile/ZipFile.h | 2 +- lib/hal/HalStorage.cpp | 1 - lib/hal/HalStorage.h | 7 ----- src/CrossPointSettings.cpp | 6 ++-- src/CrossPointSettings.h | 2 +- src/CrossPointState.cpp | 2 +- src/FontInstaller.cpp | 2 +- src/RecentBooksStore.cpp | 2 +- src/WifiCredentialStore.cpp | 2 +- src/activities/boot_sleep/SleepActivity.cpp | 6 ++-- src/activities/reader/EpubReaderActivity.cpp | 2 +- src/activities/reader/EpubReaderUtils.h | 2 +- src/activities/reader/TxtReaderActivity.cpp | 8 +++--- src/activities/reader/XtcReaderActivity.cpp | 4 +-- .../settings/FontDownloadActivity.cpp | 6 ++-- src/activities/util/BmpViewerActivity.cpp | 4 +-- src/components/themes/BaseTheme.cpp | 4 +-- .../themes/lyra/Lyra3CoversTheme.cpp | 2 +- src/components/themes/lyra/LyraTheme.cpp | 2 +- .../themes/roundedraff/RoundedRaffTheme.cpp | 2 +- src/main.cpp | 4 +-- src/network/CrossPointWebServer.cpp | 28 +++++++++++-------- src/network/CrossPointWebServer.h | 4 +-- src/network/HttpDownloader.cpp | 2 +- src/network/WebDAVHandler.cpp | 22 +++++++-------- src/network/WebDAVHandler.h | 2 +- src/util/ScreenshotUtil.cpp | 2 +- 63 files changed, 201 insertions(+), 205 deletions(-) diff --git a/.skills/SKILL.md b/.skills/SKILL.md index 848ea462..0a6775f3 100644 --- a/.skills/SKILL.md +++ b/.skills/SKILL.md @@ -152,20 +152,19 @@ These flags in `platformio.ini` fundamentally affect firmware behavior: #include // Use Storage singleton (defined via macro) -FsFile file; +HalFile file; if (Storage.openFileForRead("MODULE", "/path/to/file.bin", file)) { // Read from file // No file.close() needed — DESTRUCTOR_CLOSES_FILE=1 handles it at scope exit } ``` -**Usage**: See example above. Uses `FsFile` (SdFat), NOT Arduino `File`. Do NOT add `file.close()` for local variables (see DESTRUCTOR_CLOSES_FILE above). +**Usage**: Use `HalFile` (the mutex-wrapping handle), NOT raw SdFat `FsFile` or Arduino `File`. Do NOT add `file.close()` for local variables (see DESTRUCTOR_CLOSES_FILE above). **SdFat is not thread-safe; all SD access MUST go through HalStorage**: - SdFat's `SdSpiCard` tracks SPI bus state with an unsynchronized `m_spiActive` bool. Two tasks calling SdFat concurrently can confuse that state machine and end with one task calling `SPIClass::endTransaction()` against a paramLock the *other* task is holding. That trips FreeRTOS's `xTaskPriorityDisinherit` assert (`tasks.c:5156, pxTCB == pxCurrentTCBs[0]`) and panics the system. See SdFat issue #518. -- `HalStorage` serializes everything via `storageMutex`. Downstream code includes ``, which transparently `using FsFile = HalFile;`; every method call (read, write, seek, close) takes the mutex. `HalFile`'s destructor also takes the mutex before letting the underlying SdFat `FsFile` close. -- **Never** call into `SdFat` / `SdSpiCard` / `FsBaseFile` / `SDCardManager` directly. **Never** define `HAL_STORAGE_IMPL` outside `HalStorage.cpp`; that disables the `FsFile -> HalFile` typedef and you'll get a raw SdFat handle that bypasses the mutex. -- If you're storing a raw `FsFile` in a place that won't transitively include `` (rare), include the header explicitly so the typedef applies. +- `HalStorage` serializes everything via `storageMutex`. Downstream code uses `HalFile` (declared in ``); every method call (read, write, seek, close) takes the mutex. `HalFile`'s destructor also takes the mutex before letting the underlying SdFat `FsFile` close. +- **Never** call into `SdFat` / `SdSpiCard` / `FsBaseFile` / `SDCardManager` / raw `FsFile` directly — that bypasses the mutex. --- diff --git a/lib/EpdFont/SdCardFont.cpp b/lib/EpdFont/SdCardFont.cpp index 6c860949..1c48f278 100644 --- a/lib/EpdFont/SdCardFont.cpp +++ b/lib/EpdFont/SdCardFont.cpp @@ -168,7 +168,7 @@ bool SdCardFont::loadStyleKernLigatureData(PerStyle& s) { return true; } - FsFile file; + HalFile file; if (!Storage.openFileForRead("SDCF", filePath_, file)) { LOG_ERR("SDCF", "Failed to open .cpfont for kern/lig: %s", filePath_); return false; @@ -345,7 +345,7 @@ bool SdCardFont::buildMiniKernMatrix(PerStyle& s, const uint32_t* codepoints, ui // Step 6: read the full matrix's rows for each used left class, keep only // columns for used right classes. One SD seek + one read per used left class; // a row is kernRightClassCount bytes (~200 for Literata). - FsFile file; + HalFile file; if (!Storage.openFileForRead("SDCF", filePath_, file)) { LOG_ERR("SDCF", "Failed to open .cpfont for mini kern: %s", filePath_); freeStyleMiniKern(s); @@ -425,7 +425,7 @@ bool SdCardFont::load(const char* path) { strncpy(filePath_, path, sizeof(filePath_) - 1); filePath_[sizeof(filePath_) - 1] = '\0'; - FsFile file; + HalFile file; if (!Storage.openFileForRead("SDCF", path, file)) { LOG_ERR("SDCF", "Failed to open .cpfont: %s", path); return false; @@ -798,7 +798,7 @@ int SdCardFont::prewarmStyle(uint8_t styleIdx, const uint32_t* codepoints, uint3 std::sort(readOrder, readOrder + validCount, [&](uint32_t a, uint32_t b) { return mappings[a].globalIndex < mappings[b].globalIndex; }); - FsFile file; + HalFile file; if (!Storage.openFileForRead("SDCF", filePath_, file)) { LOG_ERR("SDCF", "Failed to reopen .cpfont for prewarm (style %u)", styleIdx); delete[] readOrder; @@ -1104,7 +1104,7 @@ int SdCardFont::fetchAdvancesForCodepoints(uint32_t* codepoints, uint32_t cpCoun [](const CpIdx& a, const CpIdx& b) { return a.glyphIndex < b.glyphIndex; }); // Open file once and read advanceX for each needed glyph. - FsFile file; + HalFile file; if (!Storage.openFileForRead("SDCF", filePath_, file)) { LOG_ERR("SDCF", "buildAdvanceTable: failed to open .cpfont for style %u", si); continue; @@ -1277,7 +1277,7 @@ const EpdGlyph* SdCardFont::onGlyphMiss(void* ctx, uint32_t codepoint) { bool wasAtCapacity = (self->overflowCount_ == OVERFLOW_CAPACITY); // Read glyph metadata into temporary - FsFile file; + HalFile file; if (!Storage.openFileForRead("SDCF", self->filePath_, file)) { LOG_ERR("SDCF", "Overflow: failed to open .cpfont"); return nullptr; diff --git a/lib/EpdFont/SdCardFontRegistry.cpp b/lib/EpdFont/SdCardFontRegistry.cpp index 2e0f145c..fe01c62e 100644 --- a/lib/EpdFont/SdCardFontRegistry.cpp +++ b/lib/EpdFont/SdCardFontRegistry.cpp @@ -77,12 +77,12 @@ bool SdCardFontRegistry::parseFilename(const char* filename, uint8_t& size, uint } void SdCardFontRegistry::scanDirectory(const char* dirPath, SdCardFontFamilyInfo& family) { - FsFile dir = Storage.open(dirPath); + HalFile dir = Storage.open(dirPath); if (!dir || !dir.isDirectory()) return; char nameBuffer[128]; while (true) { - FsFile entry = dir.openNextFile(); + HalFile entry = dir.openNextFile(); if (!entry) break; if (entry.isDirectory()) { entry.close(); @@ -126,7 +126,7 @@ void SdCardFontRegistry::scanDirectory(const char* dirPath, SdCardFontFamilyInfo // Skips families whose names already exist in `out` (de-duplicates between // the hidden and visible roots — first scan wins). void SdCardFontRegistry::scanRoot(const char* rootPath, std::vector& out) { - FsFile root = Storage.open(rootPath); + HalFile root = Storage.open(rootPath); if (!root) { LOG_DBG("SDREG", "Fonts directory not found: %s", rootPath); return; @@ -138,7 +138,7 @@ void SdCardFontRegistry::scanRoot(const char* rootPath, std::vectorrender(renderer, fontId, xPos + xOffset, yPos + yOffset); } -bool PageLine::serialize(FsFile& file) { +bool PageLine::serialize(HalFile& file) { serialization::writePod(file, xPos); serialization::writePod(file, yPos); @@ -18,7 +18,7 @@ bool PageLine::serialize(FsFile& file) { return block->serialize(file); } -std::unique_ptr PageLine::deserialize(FsFile& file) { +std::unique_ptr PageLine::deserialize(HalFile& file) { int16_t xPos; int16_t yPos; serialization::readPod(file, xPos); @@ -33,7 +33,7 @@ void PageImage::render(GfxRenderer& renderer, const int fontId, const int xOffse imageBlock->render(renderer, xPos + xOffset, yPos + yOffset); } -bool PageImage::serialize(FsFile& file) { +bool PageImage::serialize(HalFile& file) { serialization::writePod(file, xPos); serialization::writePod(file, yPos); @@ -41,7 +41,7 @@ bool PageImage::serialize(FsFile& file) { return imageBlock->serialize(file); } -std::unique_ptr PageImage::deserialize(FsFile& file) { +std::unique_ptr PageImage::deserialize(HalFile& file) { int16_t xPos; int16_t yPos; serialization::readPod(file, xPos); @@ -60,7 +60,7 @@ void PageHorizontalRule::render(GfxRenderer& renderer, const int fontId, const i renderer.drawLine(xPos + xOffset, yPos + yOffset, xPos + xOffset + width - 1, yPos + yOffset, thickness, true); } -bool PageHorizontalRule::serialize(FsFile& file) { +bool PageHorizontalRule::serialize(HalFile& file) { serialization::writePod(file, xPos); serialization::writePod(file, yPos); serialization::writePod(file, width); @@ -68,7 +68,7 @@ bool PageHorizontalRule::serialize(FsFile& file) { return true; } -std::unique_ptr PageHorizontalRule::deserialize(FsFile& file) { +std::unique_ptr PageHorizontalRule::deserialize(HalFile& file) { int16_t xPos = 0; int16_t yPos = 0; uint16_t width = 0; @@ -98,7 +98,7 @@ void Page::render(GfxRenderer& renderer, const int fontId, const int xOffset, co } } -bool Page::serialize(FsFile& file) const { +bool Page::serialize(HalFile& file) const { const uint16_t count = elements.size(); serialization::writePod(file, count); @@ -126,7 +126,7 @@ bool Page::serialize(FsFile& file) const { return true; } -std::unique_ptr Page::deserialize(FsFile& file) { +std::unique_ptr Page::deserialize(HalFile& file) { auto page = std::unique_ptr(new Page()); uint16_t count; diff --git a/lib/Epub/Epub/Page.h b/lib/Epub/Epub/Page.h index 34076433..f9ad2603 100644 --- a/lib/Epub/Epub/Page.h +++ b/lib/Epub/Epub/Page.h @@ -24,7 +24,7 @@ class PageElement { explicit PageElement(const int16_t xPos, const int16_t yPos) : xPos(xPos), yPos(yPos) {} virtual ~PageElement() = default; virtual void render(GfxRenderer& renderer, int fontId, int xOffset, int yOffset) = 0; - virtual bool serialize(FsFile& file) = 0; + virtual bool serialize(HalFile& file) = 0; virtual PageElementTag getTag() const = 0; // Add type identification }; @@ -37,9 +37,9 @@ class PageLine final : public PageElement { : PageElement(xPos, yPos), block(std::move(block)) {} const std::shared_ptr& getBlock() const { return block; } void render(GfxRenderer& renderer, int fontId, int xOffset, int yOffset) override; - bool serialize(FsFile& file) override; + bool serialize(HalFile& file) override; PageElementTag getTag() const override { return TAG_PageLine; } - static std::unique_ptr deserialize(FsFile& file); + static std::unique_ptr deserialize(HalFile& file); }; // New PageImage class @@ -50,9 +50,9 @@ class PageImage final : public PageElement { PageImage(std::shared_ptr block, const int16_t xPos, const int16_t yPos) : PageElement(xPos, yPos), imageBlock(std::move(block)) {} void render(GfxRenderer& renderer, int fontId, int xOffset, int yOffset) override; - bool serialize(FsFile& file) override; + bool serialize(HalFile& file) override; PageElementTag getTag() const override { return TAG_PageImage; } - static std::unique_ptr deserialize(FsFile& file); + static std::unique_ptr deserialize(HalFile& file); const ImageBlock& getImageBlock() const { return *imageBlock; } }; @@ -65,9 +65,9 @@ class PageHorizontalRule final : public PageElement { : PageElement(xPos, yPos), width(width), thickness(thickness) {} void render(GfxRenderer& renderer, int fontId, int xOffset, int yOffset) override; - bool serialize(FsFile& file) override; + bool serialize(HalFile& file) override; PageElementTag getTag() const override { return TAG_PageHorizontalRule; } - static std::unique_ptr deserialize(FsFile& file); + static std::unique_ptr deserialize(HalFile& file); }; class Page { @@ -88,8 +88,8 @@ class Page { } void render(GfxRenderer& renderer, int fontId, int xOffset, int yOffset) const; - bool serialize(FsFile& file) const; - static std::unique_ptr deserialize(FsFile& file); + bool serialize(HalFile& file) const; + static std::unique_ptr deserialize(HalFile& file); // Check if page contains any images (used to force full refresh) bool hasImages() const { diff --git a/lib/Epub/Epub/Section.cpp b/lib/Epub/Epub/Section.cpp index 30f0ef47..5777a7d2 100644 --- a/lib/Epub/Epub/Section.cpp +++ b/lib/Epub/Epub/Section.cpp @@ -176,7 +176,7 @@ bool Section::createSectionFile(const int fontId, const float lineCompression, c Storage.remove(tmpHtmlPath.c_str()); } - FsFile tmpHtml; + HalFile tmpHtml; if (!Storage.openFileForWrite("SCT", tmpHtmlPath, tmpHtml)) { continue; } @@ -317,7 +317,7 @@ std::unique_ptr Section::loadPageFromSectionFile() { } std::optional Section::getPageForAnchor(const std::string& anchor) const { - FsFile f; + HalFile f; if (!Storage.openFileForRead("SCT", filePath, f)) { return std::nullopt; } @@ -347,7 +347,7 @@ std::optional Section::getPageForAnchor(const std::string& anchor) con } std::optional Section::getPageForParagraphIndex(const uint16_t pIndex) const { - FsFile f; + HalFile f; if (!Storage.openFileForRead("SCT", filePath, f)) { return std::nullopt; } @@ -386,7 +386,7 @@ std::optional Section::getPageForParagraphIndex(const uint16_t pIndex) } std::optional Section::getParagraphIndexForPage(const uint16_t page) const { - FsFile f; + HalFile f; if (!Storage.openFileForRead("SCT", filePath, f)) { return std::nullopt; } @@ -418,7 +418,7 @@ std::optional Section::getParagraphIndexForPage(const uint16_t page) c } std::optional Section::getPageForListItemIndex(const uint16_t liIndex) const { - FsFile f; + HalFile f; if (!Storage.openFileForRead("SCT", filePath, f)) { return std::nullopt; } diff --git a/lib/Epub/Epub/Section.h b/lib/Epub/Epub/Section.h index aea02d34..e2869d2a 100644 --- a/lib/Epub/Epub/Section.h +++ b/lib/Epub/Epub/Section.h @@ -14,7 +14,7 @@ class Section { const int spineIndex; GfxRenderer& renderer; std::string filePath; - FsFile file; + HalFile file; void writeSectionFileHeader(int fontId, float lineCompression, bool extraParagraphSpacing, uint8_t paragraphAlignment, uint16_t viewportWidth, uint16_t viewportHeight, bool hyphenationEnabled, diff --git a/lib/Epub/Epub/blocks/ImageBlock.cpp b/lib/Epub/Epub/blocks/ImageBlock.cpp index 012dcf5f..ddf99f90 100644 --- a/lib/Epub/Epub/blocks/ImageBlock.cpp +++ b/lib/Epub/Epub/blocks/ImageBlock.cpp @@ -30,7 +30,7 @@ std::string getCachePath(const std::string& imagePath) { bool renderFromCache(GfxRenderer& renderer, const std::string& cachePath, int x, int y, int expectedWidth, int expectedHeight) { - FsFile cacheFile; + HalFile cacheFile; if (!Storage.openFileForRead("IMG", cachePath, cacheFile)) { return false; } @@ -112,7 +112,7 @@ void ImageBlock::render(GfxRenderer& renderer, const int x, const int y) { // No cache - need to decode the image // Check if image file exists - FsFile file; + HalFile file; if (!Storage.openFileForRead("IMG", imagePath, file)) { LOG_ERR("IMG", "Image file not found: %s", imagePath.c_str()); return; @@ -155,14 +155,14 @@ void ImageBlock::render(GfxRenderer& renderer, const int x, const int y) { LOG_DBG("IMG", "Decode successful"); } -bool ImageBlock::serialize(FsFile& file) { +bool ImageBlock::serialize(HalFile& file) { serialization::writeString(file, imagePath); serialization::writePod(file, width); serialization::writePod(file, height); return true; } -std::unique_ptr ImageBlock::deserialize(FsFile& file) { +std::unique_ptr ImageBlock::deserialize(HalFile& file) { std::string path; serialization::readString(file, path); int16_t w, h; diff --git a/lib/Epub/Epub/blocks/ImageBlock.h b/lib/Epub/Epub/blocks/ImageBlock.h index f3b01e6c..e6cccae7 100644 --- a/lib/Epub/Epub/blocks/ImageBlock.h +++ b/lib/Epub/Epub/blocks/ImageBlock.h @@ -21,8 +21,8 @@ class ImageBlock final : public Block { bool isEmpty() override { return false; } void render(GfxRenderer& renderer, const int x, const int y); - bool serialize(FsFile& file); - static std::unique_ptr deserialize(FsFile& file); + bool serialize(HalFile& file); + static std::unique_ptr deserialize(HalFile& file); private: std::string imagePath; diff --git a/lib/Epub/Epub/blocks/TextBlock.cpp b/lib/Epub/Epub/blocks/TextBlock.cpp index 9acd8b03..0f132d52 100644 --- a/lib/Epub/Epub/blocks/TextBlock.cpp +++ b/lib/Epub/Epub/blocks/TextBlock.cpp @@ -67,7 +67,7 @@ void TextBlock::render(const GfxRenderer& renderer, const int fontId, const int } } -bool TextBlock::serialize(FsFile& file) const { +bool TextBlock::serialize(HalFile& file) const { // Focus annotations are optional; vectors are either empty (no splits in this block) // or sized in lockstep with words[]. const bool hasFocus = !wordFocusBoundary.empty(); @@ -110,7 +110,7 @@ bool TextBlock::serialize(FsFile& file) const { return true; } -std::unique_ptr TextBlock::deserialize(FsFile& file) { +std::unique_ptr TextBlock::deserialize(HalFile& file) { uint16_t wc; std::vector words; std::vector wordXpos; diff --git a/lib/Epub/Epub/blocks/TextBlock.h b/lib/Epub/Epub/blocks/TextBlock.h index e60b283c..5f4bf80e 100644 --- a/lib/Epub/Epub/blocks/TextBlock.h +++ b/lib/Epub/Epub/blocks/TextBlock.h @@ -47,6 +47,6 @@ class TextBlock final : public Block { // given a renderer works out where to break the words into lines void render(const GfxRenderer& renderer, int fontId, int x, int y) const; BlockType getType() override { return TEXT_BLOCK; } - bool serialize(FsFile& file) const; - static std::unique_ptr deserialize(FsFile& file); + bool serialize(HalFile& file) const; + static std::unique_ptr deserialize(HalFile& file); }; diff --git a/lib/Epub/Epub/converters/JpegToFramebufferConverter.cpp b/lib/Epub/Epub/converters/JpegToFramebufferConverter.cpp index a21a59aa..79810f33 100644 --- a/lib/Epub/Epub/converters/JpegToFramebufferConverter.cpp +++ b/lib/Epub/Epub/converters/JpegToFramebufferConverter.cpp @@ -19,7 +19,7 @@ namespace { // Context struct passed through JPEGDEC callbacks to avoid global mutable state. // The draw callback receives this via pDraw->pUser (set by setUserPointer()). -// The file I/O callbacks receive the FsFile* via pFile->fHandle (set by jpegOpen()). +// The file I/O callbacks receive the HalFile* via pFile->fHandle (set by jpegOpen()). struct JpegContext { GfxRenderer* renderer{nullptr}; const RenderConfig* config{nullptr}; @@ -48,10 +48,10 @@ struct JpegContext { bool caching{false}; }; -// File I/O callbacks use pFile->fHandle to access the FsFile*, +// File I/O callbacks use pFile->fHandle to access the HalFile*, // avoiding the need for global file state. void* jpegOpen(const char* filename, int32_t* size) { - FsFile* f = new FsFile(); + HalFile* f = new HalFile(); if (!Storage.openFileForRead("JPG", std::string(filename), *f)) { delete f; return nullptr; @@ -61,7 +61,7 @@ void* jpegOpen(const char* filename, int32_t* size) { } void jpegClose(void* handle) { - FsFile* f = reinterpret_cast(handle); + HalFile* f = reinterpret_cast(handle); if (f) { f->close(); delete f; @@ -73,7 +73,7 @@ void jpegClose(void* handle) { // MUST maintain iPos to match the actual file position, otherwise progressive // JPEGs with large headers fail during parsing. int32_t jpegRead(JPEGFILE* pFile, uint8_t* pBuf, int32_t len) { - FsFile* f = reinterpret_cast(pFile->fHandle); + HalFile* f = reinterpret_cast(pFile->fHandle); if (!f) return 0; int32_t bytesRead = f->read(pBuf, len); if (bytesRead < 0) return 0; @@ -82,7 +82,7 @@ int32_t jpegRead(JPEGFILE* pFile, uint8_t* pBuf, int32_t len) { } int32_t jpegSeek(JPEGFILE* pFile, int32_t pos) { - FsFile* f = reinterpret_cast(pFile->fHandle); + HalFile* f = reinterpret_cast(pFile->fHandle); if (!f) return -1; if (!f->seek(pos)) return -1; pFile->iPos = pos; diff --git a/lib/Epub/Epub/converters/PixelCache.h b/lib/Epub/Epub/converters/PixelCache.h index c911818d..10c88acf 100644 --- a/lib/Epub/Epub/converters/PixelCache.h +++ b/lib/Epub/Epub/converters/PixelCache.h @@ -56,7 +56,7 @@ struct PixelCache { bool writeToFile(const std::string& cachePath) { if (!buffer) return false; - FsFile cacheFile; + HalFile cacheFile; if (!Storage.openFileForWrite("IMG", cachePath, cacheFile)) { LOG_ERR("IMG", "Failed to open cache file for writing: %s", cachePath.c_str()); return false; diff --git a/lib/Epub/Epub/converters/PngToFramebufferConverter.cpp b/lib/Epub/Epub/converters/PngToFramebufferConverter.cpp index 245f5c4f..1ebe77ab 100644 --- a/lib/Epub/Epub/converters/PngToFramebufferConverter.cpp +++ b/lib/Epub/Epub/converters/PngToFramebufferConverter.cpp @@ -19,7 +19,7 @@ namespace { // Context struct passed through PNGdec callbacks to avoid global mutable state. // The draw callback receives this via pDraw->pUser (set by png.decode()). -// The file I/O callbacks receive the FsFile* via pFile->fHandle (set by pngOpen()). +// The file I/O callbacks receive the HalFile* via pFile->fHandle (set by pngOpen()). struct PngContext { GfxRenderer* renderer{nullptr}; const RenderConfig* config{nullptr}; @@ -40,10 +40,10 @@ struct PngContext { uint8_t* grayLineBuffer{nullptr}; }; -// File I/O callbacks use pFile->fHandle to access the FsFile*, +// File I/O callbacks use pFile->fHandle to access the HalFile*, // avoiding the need for global file state. void* pngOpenWithHandle(const char* filename, int32_t* size) { - FsFile* f = new FsFile(); + HalFile* f = new HalFile(); if (!Storage.openFileForRead("PNG", std::string(filename), *f)) { delete f; return nullptr; @@ -53,7 +53,7 @@ void* pngOpenWithHandle(const char* filename, int32_t* size) { } void pngCloseWithHandle(void* handle) { - FsFile* f = reinterpret_cast(handle); + HalFile* f = reinterpret_cast(handle); if (f) { f->close(); delete f; @@ -61,13 +61,13 @@ void pngCloseWithHandle(void* handle) { } int32_t pngReadWithHandle(PNGFILE* pFile, uint8_t* pBuf, int32_t len) { - FsFile* f = reinterpret_cast(pFile->fHandle); + HalFile* f = reinterpret_cast(pFile->fHandle); if (!f) return 0; return f->read(pBuf, len); } int32_t pngSeekWithHandle(PNGFILE* pFile, int32_t pos) { - FsFile* f = reinterpret_cast(pFile->fHandle); + HalFile* f = reinterpret_cast(pFile->fHandle); if (!f) return -1; return f->seek(pos); } diff --git a/lib/Epub/Epub/css/CssParser.cpp b/lib/Epub/Epub/css/CssParser.cpp index 8f7237e5..38be4bcf 100644 --- a/lib/Epub/Epub/css/CssParser.cpp +++ b/lib/Epub/Epub/css/CssParser.cpp @@ -460,7 +460,7 @@ void CssParser::processRuleBlockWithStyle(const std::string& selectorGroup, cons // Main parsing entry point -bool CssParser::loadFromStream(FsFile& source) { +bool CssParser::loadFromStream(HalFile& source) { if (!source) { LOG_ERR("CSS", "Cannot read from invalid file"); return false; @@ -676,7 +676,7 @@ bool CssParser::saveToCache() const { return false; } - FsFile file; + HalFile file; if (!Storage.openFileForWrite("CSS", cachePath + rulesCache, file)) { return false; } @@ -751,7 +751,7 @@ bool CssParser::loadFromCache() { return false; } - FsFile file; + HalFile file; if (!Storage.openFileForRead("CSS", cachePath + rulesCache, file)) { return false; } diff --git a/lib/Epub/Epub/css/CssParser.h b/lib/Epub/Epub/css/CssParser.h index 69bc3ec2..004a232d 100644 --- a/lib/Epub/Epub/css/CssParser.h +++ b/lib/Epub/Epub/css/CssParser.h @@ -46,7 +46,7 @@ class CssParser { * @param source Open file handle to read from * @return true if parsing completed (even if no rules found) */ - bool loadFromStream(FsFile& source); + bool loadFromStream(HalFile& source); /** * Look up the style for an HTML element, considering tag name and class attributes. diff --git a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp index 89184d5d..072dc0c6 100644 --- a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp +++ b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp @@ -380,7 +380,7 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char* std::string cachedImagePath = self->imageBasePath + std::to_string(self->imageCounter++) + ext; // Extract image to cache file - FsFile cachedImageFile; + HalFile cachedImageFile; bool extractSuccess = false; if (Storage.openFileForWrite("EHP", cachedImagePath, cachedImageFile)) { extractSuccess = self->epub->readItemContentsToStream(resolvedPath, cachedImageFile, 4096); @@ -1150,7 +1150,7 @@ bool ChapterHtmlSlimParser::parseAndBuildPages() { // Using DefaultHandlerExpand preserves normal entity expansion from DOCTYPE XML_SetDefaultHandlerExpand(parser, defaultHandlerExpand); - FsFile file; + HalFile file; if (!Storage.openFileForRead("EHP", filepath, file)) { destroyXmlParser(parser); return false; diff --git a/lib/Epub/Epub/parsers/ContentOpfParser.h b/lib/Epub/Epub/parsers/ContentOpfParser.h index 485b3a85..0a0e51ba 100644 --- a/lib/Epub/Epub/parsers/ContentOpfParser.h +++ b/lib/Epub/Epub/parsers/ContentOpfParser.h @@ -29,7 +29,7 @@ class ContentOpfParser final : public Print { XML_Parser parser = nullptr; ParserState state = START; BookMetadataCache* cache; - FsFile tempItemStore; + HalFile tempItemStore; std::string coverItemId; // Index for fast idref→href lookup (used only for large EPUBs) diff --git a/lib/GfxRenderer/Bitmap.cpp b/lib/GfxRenderer/Bitmap.cpp index 776e52f3..867fbf2b 100644 --- a/lib/GfxRenderer/Bitmap.cpp +++ b/lib/GfxRenderer/Bitmap.cpp @@ -21,7 +21,7 @@ Bitmap::~Bitmap() { delete fsDitherer; } -uint16_t Bitmap::readLE16(FsFile& f) { +uint16_t Bitmap::readLE16(HalFile& f) { const int c0 = f.read(); const int c1 = f.read(); const auto b0 = static_cast(c0 < 0 ? 0 : c0); @@ -29,7 +29,7 @@ uint16_t Bitmap::readLE16(FsFile& f) { return static_cast(b0) | (static_cast(b1) << 8); } -uint32_t Bitmap::readLE32(FsFile& f) { +uint32_t Bitmap::readLE32(HalFile& f) { const int c0 = f.read(); const int c1 = f.read(); const int c2 = f.read(); diff --git a/lib/GfxRenderer/Bitmap.h b/lib/GfxRenderer/Bitmap.h index bba4189f..5a57c5f5 100644 --- a/lib/GfxRenderer/Bitmap.h +++ b/lib/GfxRenderer/Bitmap.h @@ -64,7 +64,7 @@ class Bitmap { public: static const char* errorToString(BmpReaderError err); - explicit Bitmap(FsFile& file, bool dithering = false) : file(file), dithering(dithering) {} + explicit Bitmap(HalFile& file, bool dithering = false) : file(file), dithering(dithering) {} ~Bitmap(); BmpReaderError parseHeaders(); BmpReaderError readNextRow(uint8_t* data, uint8_t* rowBuffer) const; @@ -78,10 +78,10 @@ class Bitmap { uint16_t getBpp() const { return bpp; } private: - static uint16_t readLE16(FsFile& f); - static uint32_t readLE32(FsFile& f); + static uint16_t readLE16(HalFile& f); + static uint32_t readLE32(HalFile& f); - FsFile& file; + HalFile& file; bool dithering = false; int width = 0; int height = 0; diff --git a/lib/InflateReader/InflateReader.h b/lib/InflateReader/InflateReader.h index 1093c09a..ce090d15 100644 --- a/lib/InflateReader/InflateReader.h +++ b/lib/InflateReader/InflateReader.h @@ -25,7 +25,7 @@ enum class InflateStatus { // // struct MyCtx { // InflateReader reader; // must be first -// FsFile* file; +// HalFile* file; // // ... // }; // static int myCb(struct uzlib_uncomp* u) { diff --git a/lib/JpegToBmpConverter/JpegToBmpConverter.cpp b/lib/JpegToBmpConverter/JpegToBmpConverter.cpp index 2c9545b2..2b8f2b53 100644 --- a/lib/JpegToBmpConverter/JpegToBmpConverter.cpp +++ b/lib/JpegToBmpConverter/JpegToBmpConverter.cpp @@ -167,7 +167,7 @@ constexpr size_t MIN_FREE_HEAP = JPEG_DECODER_SIZE + 32 * 1024; // Static file pointer for JPEGDEC open callback. // Safe in single-threaded embedded context; never accessed concurrently. -static FsFile* s_jpegFile = nullptr; +static HalFile* s_jpegFile = nullptr; void* bmpJpegOpen(const char* /*filename*/, int32_t* size) { if (!s_jpegFile || !*s_jpegFile) return nullptr; @@ -181,7 +181,7 @@ void bmpJpegClose(void* /*handle*/) { } int32_t bmpJpegRead(JPEGFILE* pFile, uint8_t* pBuf, int32_t len) { - auto* f = reinterpret_cast(pFile->fHandle); + auto* f = reinterpret_cast(pFile->fHandle); if (!f) return 0; int32_t n = f->read(pBuf, len); if (n < 0) n = 0; @@ -190,7 +190,7 @@ int32_t bmpJpegRead(JPEGFILE* pFile, uint8_t* pBuf, int32_t len) { } int32_t bmpJpegSeek(JPEGFILE* pFile, int32_t pos) { - auto* f = reinterpret_cast(pFile->fHandle); + auto* f = reinterpret_cast(pFile->fHandle); if (!f || !f->seek(pos)) return -1; pFile->iPos = pos; return pos; @@ -376,8 +376,8 @@ int bmpDrawCallback(JPEGDRAW* pDraw) { } // namespace // Internal implementation with configurable target size and bit depth -bool JpegToBmpConverter::jpegFileToBmpStreamInternal(FsFile& jpegFile, Print& bmpOut, int targetWidth, int targetHeight, - bool oneBit, bool crop) { +bool JpegToBmpConverter::jpegFileToBmpStreamInternal(HalFile& jpegFile, Print& bmpOut, int targetWidth, + int targetHeight, bool oneBit, bool crop) { LOG_DBG("JPG", "Converting JPEG to %s BMP (target: %dx%d)", oneBit ? "1-bit" : "2-bit", targetWidth, targetHeight); if (ESP.getFreeHeap() < MIN_FREE_HEAP) { @@ -532,7 +532,7 @@ bool JpegToBmpConverter::jpegFileToBmpStreamInternal(FsFile& jpegFile, Print& bm } // Core function: Convert JPEG file to 2-bit BMP (uses default target size) -bool JpegToBmpConverter::jpegFileToBmpStream(FsFile& jpegFile, Print& bmpOut, bool crop) { +bool JpegToBmpConverter::jpegFileToBmpStream(HalFile& jpegFile, Print& bmpOut, bool crop) { // Use runtime display dimensions (swapped for portrait cover sizing) const int targetWidth = display.getDisplayHeight(); const int targetHeight = display.getDisplayWidth(); @@ -540,13 +540,13 @@ bool JpegToBmpConverter::jpegFileToBmpStream(FsFile& jpegFile, Print& bmpOut, bo } // Convert with custom target size (for thumbnails, 2-bit) -bool JpegToBmpConverter::jpegFileToBmpStreamWithSize(FsFile& jpegFile, Print& bmpOut, int targetMaxWidth, +bool JpegToBmpConverter::jpegFileToBmpStreamWithSize(HalFile& jpegFile, Print& bmpOut, int targetMaxWidth, int targetMaxHeight) { return jpegFileToBmpStreamInternal(jpegFile, bmpOut, targetMaxWidth, targetMaxHeight, false); } // Convert to 1-bit BMP (black and white only, no grays) for fast home screen rendering -bool JpegToBmpConverter::jpegFileTo1BitBmpStreamWithSize(FsFile& jpegFile, Print& bmpOut, int targetMaxWidth, +bool JpegToBmpConverter::jpegFileTo1BitBmpStreamWithSize(HalFile& jpegFile, Print& bmpOut, int targetMaxWidth, int targetMaxHeight) { return jpegFileToBmpStreamInternal(jpegFile, bmpOut, targetMaxWidth, targetMaxHeight, true, true); } diff --git a/lib/JpegToBmpConverter/JpegToBmpConverter.h b/lib/JpegToBmpConverter/JpegToBmpConverter.h index 66f77f67..eae2d36f 100644 --- a/lib/JpegToBmpConverter/JpegToBmpConverter.h +++ b/lib/JpegToBmpConverter/JpegToBmpConverter.h @@ -6,13 +6,14 @@ class Print; class ZipFile; class JpegToBmpConverter { - static bool jpegFileToBmpStreamInternal(FsFile& jpegFile, Print& bmpOut, int targetWidth, int targetHeight, + static bool jpegFileToBmpStreamInternal(HalFile& jpegFile, Print& bmpOut, int targetWidth, int targetHeight, bool oneBit, bool crop = true); public: - static bool jpegFileToBmpStream(FsFile& jpegFile, Print& bmpOut, bool crop = true); + static bool jpegFileToBmpStream(HalFile& jpegFile, Print& bmpOut, bool crop = true); // Convert with custom target size (for thumbnails) - static bool jpegFileToBmpStreamWithSize(FsFile& jpegFile, Print& bmpOut, int targetMaxWidth, int targetMaxHeight); + static bool jpegFileToBmpStreamWithSize(HalFile& jpegFile, Print& bmpOut, int targetMaxWidth, int targetMaxHeight); // Convert to 1-bit BMP (black and white only, no grays) for fast home screen rendering - static bool jpegFileTo1BitBmpStreamWithSize(FsFile& jpegFile, Print& bmpOut, int targetMaxWidth, int targetMaxHeight); + static bool jpegFileTo1BitBmpStreamWithSize(HalFile& jpegFile, Print& bmpOut, int targetMaxWidth, + int targetMaxHeight); }; diff --git a/lib/KOReaderSync/KOReaderCredentialStore.cpp b/lib/KOReaderSync/KOReaderCredentialStore.cpp index f7528c5a..3b96eb50 100644 --- a/lib/KOReaderSync/KOReaderCredentialStore.cpp +++ b/lib/KOReaderSync/KOReaderCredentialStore.cpp @@ -73,7 +73,7 @@ bool KOReaderCredentialStore::loadFromFile() { } bool KOReaderCredentialStore::loadFromBinaryFile() { - FsFile file; + HalFile file; if (!Storage.openFileForRead("KRS", KOREADER_FILE_BIN, file)) { return false; } diff --git a/lib/KOReaderSync/KOReaderDocumentId.cpp b/lib/KOReaderSync/KOReaderDocumentId.cpp index 88721419..39fe2b10 100644 --- a/lib/KOReaderSync/KOReaderDocumentId.cpp +++ b/lib/KOReaderSync/KOReaderDocumentId.cpp @@ -42,7 +42,7 @@ size_t KOReaderDocumentId::getOffset(int i) { } std::string KOReaderDocumentId::calculate(const std::string& filePath) { - FsFile file; + HalFile file; if (!Storage.openFileForRead("KODoc", filePath, file)) { LOG_DBG("KODoc", "Failed to open file: %s", filePath.c_str()); return ""; diff --git a/lib/PngToBmpConverter/PngToBmpConverter.cpp b/lib/PngToBmpConverter/PngToBmpConverter.cpp index 5a8c4752..5332b8f6 100644 --- a/lib/PngToBmpConverter/PngToBmpConverter.cpp +++ b/lib/PngToBmpConverter/PngToBmpConverter.cpp @@ -73,7 +73,7 @@ enum PngFilter : uint8_t { }; // Read a big-endian 32-bit value from file -bool readBE32(FsFile& file, uint32_t& value) { +bool readBE32(HalFile& file, uint32_t& value) { uint8_t buf[4]; if (file.read(buf, 4) != 4) return false; value = (static_cast(buf[0]) << 24) | (static_cast(buf[1]) << 16) | @@ -177,7 +177,7 @@ void writeBmpHeader2bit(Print& bmpOut, const int width, const int height) { // IMPORTANT: reader must be the first field - the uzlib callback casts uzlib_uncomp* to PngDecodeContext* struct PngDecodeContext { InflateReader reader; // Must be first — callback casts uzlib_uncomp* to PngDecodeContext* - FsFile* file; + HalFile* file; // PNG image properties uint32_t width; @@ -395,7 +395,7 @@ static void convertScanlineToGray(const PngDecodeContext& ctx, uint8_t* grayRow) } } -bool PngToBmpConverter::pngFileToBmpStreamInternal(FsFile& pngFile, Print& bmpOut, int targetWidth, int targetHeight, +bool PngToBmpConverter::pngFileToBmpStreamInternal(HalFile& pngFile, Print& bmpOut, int targetWidth, int targetHeight, bool oneBit, bool crop) { LOG_DBG("PNG", "Converting PNG to %s BMP (target: %dx%d)", oneBit ? "1-bit" : "2-bit", targetWidth, targetHeight); @@ -820,19 +820,19 @@ bool PngToBmpConverter::pngFileToBmpStreamInternal(FsFile& pngFile, Print& bmpOu return success; } -bool PngToBmpConverter::pngFileToBmpStream(FsFile& pngFile, Print& bmpOut, bool crop) { +bool PngToBmpConverter::pngFileToBmpStream(HalFile& pngFile, Print& bmpOut, bool crop) { // Use runtime display dimensions (swapped for portrait cover sizing) const int targetWidth = display.getDisplayHeight(); const int targetHeight = display.getDisplayWidth(); return pngFileToBmpStreamInternal(pngFile, bmpOut, targetWidth, targetHeight, false, crop); } -bool PngToBmpConverter::pngFileToBmpStreamWithSize(FsFile& pngFile, Print& bmpOut, int targetMaxWidth, +bool PngToBmpConverter::pngFileToBmpStreamWithSize(HalFile& pngFile, Print& bmpOut, int targetMaxWidth, int targetMaxHeight) { return pngFileToBmpStreamInternal(pngFile, bmpOut, targetMaxWidth, targetMaxHeight, false); } -bool PngToBmpConverter::pngFileTo1BitBmpStreamWithSize(FsFile& pngFile, Print& bmpOut, int targetMaxWidth, +bool PngToBmpConverter::pngFileTo1BitBmpStreamWithSize(HalFile& pngFile, Print& bmpOut, int targetMaxWidth, int targetMaxHeight) { return pngFileToBmpStreamInternal(pngFile, bmpOut, targetMaxWidth, targetMaxHeight, true, true); } diff --git a/lib/PngToBmpConverter/PngToBmpConverter.h b/lib/PngToBmpConverter/PngToBmpConverter.h index bf9d3a2c..7e051907 100644 --- a/lib/PngToBmpConverter/PngToBmpConverter.h +++ b/lib/PngToBmpConverter/PngToBmpConverter.h @@ -5,11 +5,11 @@ class Print; class PngToBmpConverter { - static bool pngFileToBmpStreamInternal(FsFile& pngFile, Print& bmpOut, int targetWidth, int targetHeight, bool oneBit, - bool crop = true); + static bool pngFileToBmpStreamInternal(HalFile& pngFile, Print& bmpOut, int targetWidth, int targetHeight, + bool oneBit, bool crop = true); public: - static bool pngFileToBmpStream(FsFile& pngFile, Print& bmpOut, bool crop = true); - static bool pngFileToBmpStreamWithSize(FsFile& pngFile, Print& bmpOut, int targetMaxWidth, int targetMaxHeight); - static bool pngFileTo1BitBmpStreamWithSize(FsFile& pngFile, Print& bmpOut, int targetMaxWidth, int targetMaxHeight); + static bool pngFileToBmpStream(HalFile& pngFile, Print& bmpOut, bool crop = true); + static bool pngFileToBmpStreamWithSize(HalFile& pngFile, Print& bmpOut, int targetMaxWidth, int targetMaxHeight); + static bool pngFileTo1BitBmpStreamWithSize(HalFile& pngFile, Print& bmpOut, int targetMaxWidth, int targetMaxHeight); }; diff --git a/lib/Serialization/Serialization.h b/lib/Serialization/Serialization.h index 878a2b92..3e4fe5d9 100644 --- a/lib/Serialization/Serialization.h +++ b/lib/Serialization/Serialization.h @@ -10,7 +10,7 @@ void writePod(std::ostream& os, const T& value) { } template -void writePod(FsFile& file, const T& value) { +void writePod(HalFile& file, const T& value) { file.write(reinterpret_cast(&value), sizeof(T)); } @@ -20,7 +20,7 @@ void readPod(std::istream& is, T& value) { } template -void readPod(FsFile& file, T& value) { +void readPod(HalFile& file, T& value) { file.read(reinterpret_cast(&value), sizeof(T)); } @@ -30,7 +30,7 @@ inline void writeString(std::ostream& os, const std::string& s) { os.write(s.data(), len); } -inline void writeString(FsFile& file, const std::string& s) { +inline void writeString(HalFile& file, const std::string& s) { const uint32_t len = s.size(); writePod(file, len); file.write(reinterpret_cast(s.data()), len); @@ -43,7 +43,7 @@ inline void readString(std::istream& is, std::string& s) { is.read(&s[0], len); } -inline void readString(FsFile& file, std::string& s) { +inline void readString(HalFile& file, std::string& s) { uint32_t len; readPod(file, len); s.resize(len); diff --git a/lib/Txt/Txt.cpp b/lib/Txt/Txt.cpp index b5d22259..581c8c62 100644 --- a/lib/Txt/Txt.cpp +++ b/lib/Txt/Txt.cpp @@ -21,7 +21,7 @@ bool Txt::load() { return false; } - FsFile file; + HalFile file; if (!Storage.openFileForRead("TXT", filepath, file)) { LOG_ERR("TXT", "Failed to open file: %s", filepath.c_str()); return false; @@ -115,7 +115,7 @@ bool Txt::generateCoverBmp() const { if (FsHelpers::hasBmpExtension(coverImagePath)) { // Copy BMP file to cache LOG_DBG("TXT", "Copying BMP cover image to cache"); - FsFile src, dst; + HalFile src, dst; if (!Storage.openFileForRead("TXT", coverImagePath, src)) { return false; } @@ -132,7 +132,7 @@ bool Txt::generateCoverBmp() const { } else if (FsHelpers::hasJpgExtension(coverImagePath)) { // Convert JPG/JPEG to BMP (same approach as Epub) LOG_DBG("TXT", "Generating BMP from JPG cover image"); - FsFile coverJpg, coverBmp; + HalFile coverJpg, coverBmp; if (!Storage.openFileForRead("TXT", coverImagePath, coverJpg)) { return false; } @@ -175,7 +175,7 @@ bool Txt::readContent(uint8_t* buffer, size_t offset, size_t length) const { return false; } - FsFile file; + HalFile file; if (!Storage.openFileForRead("TXT", filepath, file)) { return false; } diff --git a/lib/Xtc/Xtc.cpp b/lib/Xtc/Xtc.cpp index 5f0388d2..1142c763 100644 --- a/lib/Xtc/Xtc.cpp +++ b/lib/Xtc/Xtc.cpp @@ -166,7 +166,7 @@ bool Xtc::generateCoverBmp() const { } // Create BMP file - FsFile coverBmp; + HalFile coverBmp; if (!Storage.openFileForWrite("XTC", getCoverBmpPath(), coverBmp)) { LOG_DBG("XTC", "Failed to create cover BMP file"); free(pageBuffer); @@ -306,7 +306,7 @@ bool Xtc::generateThumbBmp(int height) const { // Page is already small enough, just use cover.bmp // Copy cover.bmp to thumb.bmp if (generateCoverBmp()) { - FsFile src, dst; + HalFile src, dst; if (Storage.openFileForRead("XTC", getCoverBmpPath(), src)) { if (Storage.openFileForWrite("XTC", getThumbBmpPath(height), dst)) { uint8_t buffer[512]; @@ -350,7 +350,7 @@ bool Xtc::generateThumbBmp(int height) const { } // Create thumbnail BMP file - use 1-bit format for fast home screen rendering (no gray passes) - FsFile thumbBmp; + HalFile thumbBmp; if (!Storage.openFileForWrite("XTC", getThumbBmpPath(height), thumbBmp)) { LOG_DBG("XTC", "Failed to create thumb BMP file"); free(pageBuffer); diff --git a/lib/Xtc/Xtc/XtcParser.cpp b/lib/Xtc/Xtc/XtcParser.cpp index 877d8237..178be7ef 100644 --- a/lib/Xtc/Xtc/XtcParser.cpp +++ b/lib/Xtc/Xtc/XtcParser.cpp @@ -530,7 +530,7 @@ XtcError XtcParser::loadPageStreaming(uint32_t pageIndex, } bool XtcParser::isValidXtcFile(const char* filepath) { - FsFile file; + HalFile file; if (!Storage.openFileForRead("XTC", filepath, file)) { return false; } diff --git a/lib/Xtc/Xtc/XtcParser.h b/lib/Xtc/Xtc/XtcParser.h index b688d793..4092f29a 100644 --- a/lib/Xtc/Xtc/XtcParser.h +++ b/lib/Xtc/Xtc/XtcParser.h @@ -84,7 +84,7 @@ class XtcParser { XtcError getLastError() const { return m_lastError; } private: - FsFile m_file; + HalFile m_file; std::string m_filepath; bool m_isOpen; XtcHeader m_header; diff --git a/lib/ZipFile/ZipFile.cpp b/lib/ZipFile/ZipFile.cpp index fe59dfaa..1c3964a1 100644 --- a/lib/ZipFile/ZipFile.cpp +++ b/lib/ZipFile/ZipFile.cpp @@ -8,7 +8,7 @@ struct ZipInflateCtx { InflateReader reader; // Must be first — callback casts uzlib_uncomp* to ZipInflateCtx* - FsFile* file = nullptr; + HalFile* file = nullptr; size_t fileRemaining = 0; uint8_t* readBuf = nullptr; size_t readBufSize = 0; diff --git a/lib/ZipFile/ZipFile.h b/lib/ZipFile/ZipFile.h index 60c97a4c..2a32e974 100644 --- a/lib/ZipFile/ZipFile.h +++ b/lib/ZipFile/ZipFile.h @@ -39,7 +39,7 @@ class ZipFile { private: const std::string& filePath; - FsFile file; + HalFile file; ZipDetails zipDetails = {0, 0, false}; std::unordered_map fileStatSlimCache; diff --git a/lib/hal/HalStorage.cpp b/lib/hal/HalStorage.cpp index 095e389c..13f50297 100644 --- a/lib/hal/HalStorage.cpp +++ b/lib/hal/HalStorage.cpp @@ -1,4 +1,3 @@ -#define HAL_STORAGE_IMPL #include "HalStorage.h" #include // need to be included before SdFat.h for compatibility with FS.h's File class diff --git a/lib/hal/HalStorage.h b/lib/hal/HalStorage.h index 5483678b..59469946 100644 --- a/lib/hal/HalStorage.h +++ b/lib/hal/HalStorage.h @@ -96,13 +96,6 @@ class HalFile : public Print { operator bool() const; }; -// Only do renaming FsFile to HalFile if this header is included by downstream code -// The renaming is to allow using the thread-safe HalFile instead of the raw FsFile, without needing to change the -// downstream code -#ifndef HAL_STORAGE_IMPL -using FsFile = HalFile; -#endif - // Downstream code must use Storage instead of SdMan #ifdef SdMan #undef SdMan diff --git a/src/CrossPointSettings.cpp b/src/CrossPointSettings.cpp index c370f8d6..cbf46e9d 100644 --- a/src/CrossPointSettings.cpp +++ b/src/CrossPointSettings.cpp @@ -14,7 +14,7 @@ // Initialize the static instance CrossPointSettings CrossPointSettings::instance; -void readAndValidate(FsFile& file, uint8_t& member, const uint8_t maxValue) { +void readAndValidate(HalFile& file, uint8_t& member, const uint8_t maxValue) { uint8_t tempValue; serialization::readPod(file, tempValue); if (tempValue < maxValue) { @@ -127,7 +127,7 @@ bool CrossPointSettings::migrateLanguageBinaryFile() { // frozen enum order from 2f969a9. if (!Storage.exists(LANG_FILE_BIN)) return false; - FsFile f; + HalFile f; if (Storage.openFileForRead("CPS", LANG_FILE_BIN, f)) { uint8_t version; serialization::readPod(f, version); @@ -146,7 +146,7 @@ bool CrossPointSettings::migrateLanguageBinaryFile() { } bool CrossPointSettings::loadFromBinaryFile() { - FsFile inputFile; + HalFile inputFile; if (!Storage.openFileForRead("CPS", SETTINGS_FILE_BIN, inputFile)) { return false; } diff --git a/src/CrossPointSettings.h b/src/CrossPointSettings.h index 352ed8d9..2be537cf 100644 --- a/src/CrossPointSettings.h +++ b/src/CrossPointSettings.h @@ -269,7 +269,7 @@ class CrossPointSettings { int getReaderFontId() const; // If count_only is true, returns the number of settings items that would be written. - uint8_t writeSettings(FsFile& file, bool count_only = false) const; + uint8_t writeSettings(HalFile& file, bool count_only = false) const; bool saveToFile() const; bool loadFromFile(); diff --git a/src/CrossPointState.cpp b/src/CrossPointState.cpp index ef7d2466..c90ce656 100644 --- a/src/CrossPointState.cpp +++ b/src/CrossPointState.cpp @@ -63,7 +63,7 @@ bool CrossPointState::loadFromFile() { } bool CrossPointState::loadFromBinaryFile() { - FsFile inputFile; + HalFile inputFile; if (!Storage.openFileForRead("CPS", STATE_FILE_BIN, inputFile)) { return false; } diff --git a/src/FontInstaller.cpp b/src/FontInstaller.cpp index cbf389ff..7ef6cda8 100644 --- a/src/FontInstaller.cpp +++ b/src/FontInstaller.cpp @@ -81,7 +81,7 @@ bool FontInstaller::ensureFamilyDir(const char* familyName) { } bool FontInstaller::validateCpfontFile(const char* path) { - FsFile file; + HalFile file; if (!Storage.openFileForRead("FONT", path, file)) { LOG_ERR("FONT", "Cannot open for validation: %s", path); return false; diff --git a/src/RecentBooksStore.cpp b/src/RecentBooksStore.cpp index 3853975a..af6e9d4c 100644 --- a/src/RecentBooksStore.cpp +++ b/src/RecentBooksStore.cpp @@ -148,7 +148,7 @@ bool RecentBooksStore::loadFromFile() { } bool RecentBooksStore::loadFromBinaryFile() { - FsFile inputFile; + HalFile inputFile; if (!Storage.openFileForRead("RBS", RECENT_BOOKS_FILE_BIN, inputFile)) { return false; } diff --git a/src/WifiCredentialStore.cpp b/src/WifiCredentialStore.cpp index 82102898..47760237 100644 --- a/src/WifiCredentialStore.cpp +++ b/src/WifiCredentialStore.cpp @@ -67,7 +67,7 @@ bool WifiCredentialStore::loadFromFile() { } bool WifiCredentialStore::loadFromBinaryFile() { - FsFile file; + HalFile file; if (!Storage.openFileForRead("WCS", WIFI_FILE_BIN, file)) { return false; } diff --git a/src/activities/boot_sleep/SleepActivity.cpp b/src/activities/boot_sleep/SleepActivity.cpp index 797db488..86fc6ab2 100644 --- a/src/activities/boot_sleep/SleepActivity.cpp +++ b/src/activities/boot_sleep/SleepActivity.cpp @@ -63,7 +63,7 @@ void SleepActivity::renderCustomSleepScreen() const { // Look for sleep.bmp on the root of the sd card to determine if we should // render a custom sleep screen instead of the default. // This takes priority over the /sleep folder. - FsFile file; + HalFile file; if (Storage.openFileForRead("SLP", "/sleep.bmp", file)) { Bitmap bitmap(file, true); if (bitmap.parseHeaders() == BmpReaderError::Ok) { @@ -129,7 +129,7 @@ void SleepActivity::renderCustomSleepScreen() const { APP_STATE.pushRecentSleep(randomFileIndex); APP_STATE.saveToFile(); const auto filename = std::string(sleepDir) + "/" + files[randomFileIndex]; - FsFile randFile; + HalFile randFile; if (Storage.openFileForRead("SLP", filename, randFile)) { LOG_DBG("SLP", "Randomly loading: %s/%s", sleepDir, files[randomFileIndex].c_str()); delay(100); @@ -304,7 +304,7 @@ void SleepActivity::renderCoverSleepScreen() const { return (this->*renderNoCoverSleepScreen)(); } - FsFile file; + HalFile file; if (Storage.openFileForRead("SLP", coverBmpPath, file)) { Bitmap bitmap(file); if (bitmap.parseHeaders() == BmpReaderError::Ok) { diff --git a/src/activities/reader/EpubReaderActivity.cpp b/src/activities/reader/EpubReaderActivity.cpp index c44e3a59..f1bde915 100644 --- a/src/activities/reader/EpubReaderActivity.cpp +++ b/src/activities/reader/EpubReaderActivity.cpp @@ -123,7 +123,7 @@ void EpubReaderActivity::onEnter() { epub->setupCacheDir(); - FsFile f; + HalFile f; if (Storage.openFileForRead("ERS", epub->getCachePath() + "/progress.bin", f)) { uint8_t data[6]; int dataSize = f.read(data, 6); diff --git a/src/activities/reader/EpubReaderUtils.h b/src/activities/reader/EpubReaderUtils.h index f2d2a747..7dc0fb63 100644 --- a/src/activities/reader/EpubReaderUtils.h +++ b/src/activities/reader/EpubReaderUtils.h @@ -13,7 +13,7 @@ inline bool saveProgress(Epub& epub, int spineIndex, int pageNumber, int pageCou LOG_ERR("ERS", "Progress values out of range: spine=%d page=%d count=%d", spineIndex, pageNumber, pageCount); return false; } - FsFile f; + HalFile f; if (!Storage.openFileForWrite("ERS", epub.getCachePath() + "/progress.bin", f)) { LOG_ERR("ERS", "Could not open progress file for write!"); return false; diff --git a/src/activities/reader/TxtReaderActivity.cpp b/src/activities/reader/TxtReaderActivity.cpp index c4c85522..4309a4a2 100644 --- a/src/activities/reader/TxtReaderActivity.cpp +++ b/src/activities/reader/TxtReaderActivity.cpp @@ -415,7 +415,7 @@ void TxtReaderActivity::renderStatusBar() const { } void TxtReaderActivity::saveProgress() const { - FsFile f; + HalFile f; if (Storage.openFileForWrite("TRS", txt->getCachePath() + "/progress.bin", f)) { uint8_t data[4]; data[0] = currentPage & 0xFF; @@ -427,7 +427,7 @@ void TxtReaderActivity::saveProgress() const { } void TxtReaderActivity::loadProgress() { - FsFile f; + HalFile f; if (Storage.openFileForRead("TRS", txt->getCachePath() + "/progress.bin", f)) { uint8_t data[4]; if (f.read(data, 4) == 4) { @@ -457,7 +457,7 @@ bool TxtReaderActivity::loadPageIndexCache() { // - N * uint32_t: page offsets std::string cachePath = txt->getCachePath() + "/index.bin"; - FsFile f; + HalFile f; if (!Storage.openFileForRead("TRS", cachePath, f)) { LOG_DBG("TRS", "No page index cache found"); return false; @@ -540,7 +540,7 @@ bool TxtReaderActivity::loadPageIndexCache() { void TxtReaderActivity::savePageIndexCache() const { std::string cachePath = txt->getCachePath() + "/index.bin"; - FsFile f; + HalFile f; if (!Storage.openFileForWrite("TRS", cachePath, f)) { LOG_ERR("TRS", "Failed to save page index cache"); return; diff --git a/src/activities/reader/XtcReaderActivity.cpp b/src/activities/reader/XtcReaderActivity.cpp index 897d3f52..c78aeea1 100644 --- a/src/activities/reader/XtcReaderActivity.cpp +++ b/src/activities/reader/XtcReaderActivity.cpp @@ -375,7 +375,7 @@ void XtcReaderActivity::renderPage() { } void XtcReaderActivity::saveProgress() const { - FsFile f; + HalFile f; if (Storage.openFileForWrite("XTR", xtc->getCachePath() + "/progress.bin", f)) { uint8_t data[4]; data[0] = currentPage & 0xFF; @@ -388,7 +388,7 @@ void XtcReaderActivity::saveProgress() const { } void XtcReaderActivity::loadProgress() { - FsFile f; + HalFile f; if (Storage.openFileForRead("XTR", xtc->getCachePath() + "/progress.bin", f)) { uint8_t data[4]; if (f.read(data, 4) == 4) { diff --git a/src/activities/settings/FontDownloadActivity.cpp b/src/activities/settings/FontDownloadActivity.cpp index 67f5cdf8..0ccae794 100644 --- a/src/activities/settings/FontDownloadActivity.cpp +++ b/src/activities/settings/FontDownloadActivity.cpp @@ -82,7 +82,7 @@ bool FontDownloadActivity::fetchAndParseManifest() { } // HTTP client is now closed — TLS buffers freed. Parse JSON from file. - FsFile manifestFile; + HalFile manifestFile; if (!Storage.openFileForRead("FONT", MANIFEST_TMP, manifestFile)) { LOG_ERR("FONT", "Failed to open temp manifest"); Storage.remove(MANIFEST_TMP); @@ -149,7 +149,7 @@ bool FontDownloadActivity::fetchAndParseManifest() { for (const auto& file : family.files) { char path[128]; FontInstaller::buildFontPath(family.name.c_str(), file.name.c_str(), path, sizeof(path)); - FsFile f; + HalFile f; if (Storage.openFileForRead("FONT", path, f)) { size_t actual = f.fileSize(); f.close(); @@ -248,7 +248,7 @@ size_t FontDownloadActivity::totalUpdateSize() const { // Standard CRC32 matching zlib/Python zlib.crc32(). bool FontDownloadActivity::computeFileCrc32(const char* path, uint32_t& outCrc) { - FsFile f; + HalFile f; if (!Storage.openFileForRead("FONT", path, f)) { return false; } diff --git a/src/activities/util/BmpViewerActivity.cpp b/src/activities/util/BmpViewerActivity.cpp index 0387bc55..def41015 100644 --- a/src/activities/util/BmpViewerActivity.cpp +++ b/src/activities/util/BmpViewerActivity.cpp @@ -63,7 +63,7 @@ void BmpViewerActivity::onEnter() { loadSiblingImages(); } - FsFile file; + HalFile file; const auto pageWidth = renderer.getScreenWidth(); const auto pageHeight = renderer.getScreenHeight(); @@ -147,7 +147,7 @@ void BmpViewerActivity::doSetSleepCover() { GUI.drawPopup(renderer, tr(STR_LOADING_POPUP)); bool success = false; - FsFile inFile, outFile; + HalFile inFile, outFile; if (Storage.openFileForRead("BMP", filePath, inFile)) { if (Storage.openFileForWrite("BMP", "/sleep.bmp", outFile)) { char buffer[2048]; diff --git a/src/components/themes/BaseTheme.cpp b/src/components/themes/BaseTheme.cpp index baa1d802..1c0c232e 100644 --- a/src/components/themes/BaseTheme.cpp +++ b/src/components/themes/BaseTheme.cpp @@ -426,7 +426,7 @@ void BaseTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std: const std::string coverBmpPath = UITheme::getCoverThumbPath(recentBooks[0].coverBmpPath, BaseMetrics::values.homeCoverHeight); - FsFile file; + HalFile file; if (Storage.openFileForRead("HOME", coverBmpPath, file)) { Bitmap bitmap(file); if (bitmap.parseHeaders() == BmpReaderError::Ok) { @@ -476,7 +476,7 @@ void BaseTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std: UITheme::getCoverThumbPath(recentBooks[0].coverBmpPath, BaseMetrics::values.homeCoverHeight); // First time: load cover from SD and render - FsFile file; + HalFile file; if (Storage.openFileForRead("HOME", coverBmpPath, file)) { Bitmap bitmap(file); if (bitmap.parseHeaders() == BmpReaderError::Ok) { diff --git a/src/components/themes/lyra/Lyra3CoversTheme.cpp b/src/components/themes/lyra/Lyra3CoversTheme.cpp index 68d8b234..fdbed623 100644 --- a/src/components/themes/lyra/Lyra3CoversTheme.cpp +++ b/src/components/themes/lyra/Lyra3CoversTheme.cpp @@ -42,7 +42,7 @@ void Lyra3CoversTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, con UITheme::getCoverThumbPath(coverPath, Lyra3CoversMetrics::values.homeCoverHeight); // First time: load cover from SD and render - FsFile file; + HalFile file; if (Storage.openFileForRead("HOME", coverBmpPath, file)) { Bitmap bitmap(file); if (bitmap.parseHeaders() == BmpReaderError::Ok) { diff --git a/src/components/themes/lyra/LyraTheme.cpp b/src/components/themes/lyra/LyraTheme.cpp index bb3b8ad4..921e99c1 100644 --- a/src/components/themes/lyra/LyraTheme.cpp +++ b/src/components/themes/lyra/LyraTheme.cpp @@ -423,7 +423,7 @@ void LyraTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std: const std::string coverBmpPath = UITheme::getCoverThumbPath(coverPath, LyraMetrics::values.homeCoverHeight); // First time: load cover from SD and render - FsFile file; + HalFile file; if (Storage.openFileForRead("HOME", coverBmpPath, file)) { Bitmap bitmap(file); if (bitmap.parseHeaders() == BmpReaderError::Ok) { diff --git a/src/components/themes/roundedraff/RoundedRaffTheme.cpp b/src/components/themes/roundedraff/RoundedRaffTheme.cpp index 3d5ea90c..50db2a8c 100644 --- a/src/components/themes/roundedraff/RoundedRaffTheme.cpp +++ b/src/components/themes/roundedraff/RoundedRaffTheme.cpp @@ -140,7 +140,7 @@ void RoundedRaffTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, con UITheme::getCoverThumbPath(coverPath, RoundedRaffMetrics::values.homeCoverHeight); // First time: load cover from SD and render - FsFile file; + HalFile file; if (Storage.openFileForRead("HOME", coverBmpPath, file)) { Bitmap bitmap(file); if (bitmap.parseHeaders() == BmpReaderError::Ok) { diff --git a/src/main.cpp b/src/main.cpp index 37af16bf..63184439 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -237,14 +237,14 @@ void waitForPowerRelease() { constexpr char SLEEP_FRAME_FILE[] = "/.crosspoint/sleep_frame.bin"; static void saveSleepFrameBuffer() { - FsFile file; + HalFile file; if (!Storage.openFileForWrite("SLP", SLEEP_FRAME_FILE, file)) return; file.write(renderer.getFrameBuffer(), renderer.getBufferSize()); file.close(); } static bool loadSleepFrameBuffer() { - FsFile file; + HalFile file; if (!Storage.openFileForRead("SLP", SLEEP_FRAME_FILE, file)) return false; const size_t bufferSize = display.getBufferSize(); const size_t bytesRead = file.read(display.getFrameBuffer(), bufferSize); diff --git a/src/network/CrossPointWebServer.cpp b/src/network/CrossPointWebServer.cpp index 41606f8d..8e251aea 100644 --- a/src/network/CrossPointWebServer.cpp +++ b/src/network/CrossPointWebServer.cpp @@ -35,7 +35,7 @@ constexpr uint16_t LOCAL_UDP_PORT = 8134; CrossPointWebServer* wsInstance = nullptr; // WebSocket upload state -FsFile wsUploadFile; +HalFile wsUploadFile; String wsUploadFileName; String wsUploadPath; size_t wsUploadSize = 0; @@ -374,7 +374,7 @@ void CrossPointWebServer::handleStatus() const { } void CrossPointWebServer::scanFiles(const char* path, const std::function& callback) const { - FsFile root = Storage.open(path); + HalFile root = Storage.open(path); if (!root) { LOG_DBG("WEB", "Failed to open directory: %s", path); return; @@ -388,7 +388,7 @@ void CrossPointWebServer::scanFiles(const char* path, const std::functionsend(500, "text/plain", "Failed to open file"); return; @@ -842,7 +842,7 @@ void CrossPointWebServer::handleRename() const { return; } - FsFile file = Storage.open(itemPath.c_str()); + HalFile file = Storage.open(itemPath.c_str()); if (!file) { server->send(500, "text/plain", "Failed to open file"); return; @@ -918,7 +918,7 @@ void CrossPointWebServer::handleMove() const { return; } - FsFile file = Storage.open(itemPath.c_str()); + HalFile file = Storage.open(itemPath.c_str()); if (!file) { server->send(500, "text/plain", "Failed to open file"); return; @@ -934,7 +934,7 @@ void CrossPointWebServer::handleMove() const { server->send(404, "text/plain", "Destination not found"); return; } - FsFile destDir = Storage.open(destPath.c_str()); + HalFile destDir = Storage.open(destPath.c_str()); if (!destDir || !destDir.isDirectory()) { if (destDir) { destDir.close(); @@ -1064,10 +1064,10 @@ void CrossPointWebServer::handleDelete() const { // Decide whether it's a directory or file by opening it bool success = false; - FsFile f = Storage.open(itemPath.c_str()); + HalFile f = Storage.open(itemPath.c_str()); if (f && f.isDirectory()) { // For folders, ensure empty before removing - FsFile entry = f.openNextFile(); + HalFile entry = f.openNextFile(); if (entry) { entry.close(); f.close(); @@ -1741,7 +1741,7 @@ void CrossPointWebServer::handleFontList() const { fileObj["name"] = name ? name + 1 : file.path.c_str(); // Stat the file for size - FsFile f; + HalFile f; if (Storage.openFileForRead("WEB", file.path.c_str(), f)) { fileObj["size"] = static_cast(f.size()); f.close(); @@ -1848,7 +1848,9 @@ void CrossPointWebServer::handleFontUploadData() { fontUpload.bytesWritten += fontUpload.bufferPos; fontUpload.bufferPos = 0; } - fontUpload.file.close(); + if (fontUpload.file) { + fontUpload.file.close(); + } if (!fontUpload.valid && !fontUpload.filePath.empty()) { Storage.remove(fontUpload.filePath.c_str()); @@ -1859,7 +1861,9 @@ void CrossPointWebServer::handleFontUploadData() { } case UPLOAD_FILE_ABORTED: { - fontUpload.file.close(); + if (fontUpload.file) { + fontUpload.file.close(); + } if (!fontUpload.filePath.empty()) { Storage.remove(fontUpload.filePath.c_str()); } diff --git a/src/network/CrossPointWebServer.h b/src/network/CrossPointWebServer.h index c5116681..fc1aaf6e 100644 --- a/src/network/CrossPointWebServer.h +++ b/src/network/CrossPointWebServer.h @@ -31,7 +31,7 @@ class CrossPointWebServer { // Used by POST upload handler struct UploadState { - FsFile file; + HalFile file; String fileName; String path = "/"; size_t size = 0; @@ -117,7 +117,7 @@ class CrossPointWebServer { // Font upload state struct FontUploadState { - FsFile file; + HalFile file; std::string familyName; std::string filePath; bool valid = false; diff --git a/src/network/HttpDownloader.cpp b/src/network/HttpDownloader.cpp index 958b5845..b4459850 100644 --- a/src/network/HttpDownloader.cpp +++ b/src/network/HttpDownloader.cpp @@ -179,7 +179,7 @@ HttpDownloader::DownloadError HttpDownloader::downloadToFile(const std::string& if (Storage.exists(destPath.c_str())) { Storage.remove(destPath.c_str()); } - FsFile file; + HalFile file; if (!Storage.openFileForWrite("HTTP", destPath.c_str(), file)) { LOG_ERR("HTTP", "Failed to open file for writing"); return FILE_ERROR; diff --git a/src/network/WebDAVHandler.cpp b/src/network/WebDAVHandler.cpp index 0fafb680..64fa3d09 100644 --- a/src/network/WebDAVHandler.cpp +++ b/src/network/WebDAVHandler.cpp @@ -67,7 +67,7 @@ void WebDAVHandler::raw(WebServer& server, const String& uri, HTTPRaw& raw) { _putExisted = Storage.exists(_putPath.c_str()); if (_putExisted) { - FsFile existing = Storage.open(_putPath.c_str()); + HalFile existing = Storage.open(_putPath.c_str()); if (existing && existing.isDirectory()) { existing.close(); _putOk = false; @@ -96,7 +96,7 @@ void WebDAVHandler::raw(WebServer& server, const String& uri, HTTPRaw& raw) { if (_putOk) { String tempPath = _putPath + ".davtmp"; if (_putExisted) Storage.remove(_putPath.c_str()); - FsFile tmp = Storage.open(tempPath.c_str()); + HalFile tmp = Storage.open(tempPath.c_str()); if (tmp) { _putOk = tmp.rename(_putPath.c_str()); tmp.close(); @@ -182,7 +182,7 @@ void WebDAVHandler::handlePropfind(WebServer& s) { return; } - FsFile root = Storage.open(path.c_str()); + HalFile root = Storage.open(path.c_str()); if (!root) { if (path == "/") { // Root should always work — send minimal response @@ -221,7 +221,7 @@ void WebDAVHandler::handlePropfind(WebServer& s) { // If depth > 0 and it's a directory, list children if (depth > 0) { - FsFile file = root.openNextFile(); + HalFile file = root.openNextFile(); char name[500]; while (file) { file.getName(name, sizeof(name)); @@ -311,7 +311,7 @@ void WebDAVHandler::handleGet(WebServer& s) { return; } - FsFile file = Storage.open(path.c_str()); + HalFile file = Storage.open(path.c_str()); if (!file) { s.send(500, "text/plain", "Failed to open file"); return; @@ -348,7 +348,7 @@ void WebDAVHandler::handleHead(WebServer& s) { return; } - FsFile file = Storage.open(path.c_str()); + HalFile file = Storage.open(path.c_str()); if (!file) { s.send(500, "text/plain", ""); return; @@ -411,7 +411,7 @@ void WebDAVHandler::handleDelete(WebServer& s) { return; } - FsFile file = Storage.open(path.c_str()); + HalFile file = Storage.open(path.c_str()); if (!file) { s.send(500, "text/plain", "Failed to open"); return; @@ -419,7 +419,7 @@ void WebDAVHandler::handleDelete(WebServer& s) { if (file.isDirectory()) { // Check if directory is empty - FsFile entry = file.openNextFile(); + HalFile entry = file.openNextFile(); if (entry) { entry.close(); file.close(); @@ -537,7 +537,7 @@ void WebDAVHandler::handleMove(WebServer& s) { Storage.remove(dstPath.c_str()); } - FsFile file = Storage.open(srcPath.c_str()); + HalFile file = Storage.open(srcPath.c_str()); if (!file) { s.send(500, "text/plain", "Failed to open source"); return; @@ -583,7 +583,7 @@ void WebDAVHandler::handleCopy(WebServer& s) { return; } - FsFile srcFile = Storage.open(srcPath.c_str()); + HalFile srcFile = Storage.open(srcPath.c_str()); if (!srcFile) { s.send(500, "text/plain", "Failed to open source"); return; @@ -617,7 +617,7 @@ void WebDAVHandler::handleCopy(WebServer& s) { Storage.remove(dstPath.c_str()); } - FsFile dstFile; + HalFile dstFile; if (!Storage.openFileForWrite("DAV", dstPath, dstFile)) { srcFile.close(); s.send(500, "text/plain", "Failed to create destination"); diff --git a/src/network/WebDAVHandler.h b/src/network/WebDAVHandler.h index e11e184b..7b21bd9c 100644 --- a/src/network/WebDAVHandler.h +++ b/src/network/WebDAVHandler.h @@ -13,7 +13,7 @@ class WebDAVHandler : public RequestHandler { private: // PUT streaming state (raw() is called in chunks) - FsFile _putFile; + HalFile _putFile; String _putPath; bool _putOk = false; bool _putExisted = false; diff --git a/src/util/ScreenshotUtil.cpp b/src/util/ScreenshotUtil.cpp index e478c3b7..32235a58 100644 --- a/src/util/ScreenshotUtil.cpp +++ b/src/util/ScreenshotUtil.cpp @@ -121,7 +121,7 @@ bool ScreenshotUtil::saveFramebufferAsBmp(const char* filename, const uint8_t* f } } - FsFile file; + HalFile file; if (!Storage.openFileForWrite("SCR", filename, file)) { LOG_ERR("SCR", "Failed to save screenshot"); return false;