This commit is contained in:
Xuan-Son Nguyen 2026-02-03 22:09:52 +00:00 committed by GitHub
commit b8ec0b73c6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 211 additions and 95 deletions

63
lib/hal/HalStorage.cpp Normal file
View File

@ -0,0 +1,63 @@
#include "HalStorage.h"
#include <SDCardManager.h>
HalStorage HalStorage::instance;
HalStorage::HalStorage() {}
bool HalStorage::begin() { return SdMan.begin(); }
bool HalStorage::ready() const { return SdMan.ready(); }
std::vector<String> HalStorage::listFiles(const char* path, int maxFiles) { return SdMan.listFiles(path, maxFiles); }
String HalStorage::readFile(const char* path) { return SdMan.readFile(path); }
bool HalStorage::readFileToStream(const char* path, Print& out, size_t chunkSize) {
return SdMan.readFileToStream(path, out, chunkSize);
}
size_t HalStorage::readFileToBuffer(const char* path, char* buffer, size_t bufferSize, size_t maxBytes) {
return SdMan.readFileToBuffer(path, buffer, bufferSize, maxBytes);
}
bool HalStorage::writeFile(const char* path, const String& content) { return SdMan.writeFile(path, content); }
bool HalStorage::ensureDirectoryExists(const char* path) { return SdMan.ensureDirectoryExists(path); }
File HalStorage::open(const char* path, const oflag_t oflag) { return SdMan.open(path, oflag); }
bool HalStorage::mkdir(const char* path, const bool pFlag) { return SdMan.mkdir(path, pFlag); }
bool HalStorage::exists(const char* path) { return SdMan.exists(path); }
bool HalStorage::remove(const char* path) { return SdMan.remove(path); }
bool HalStorage::rmdir(const char* path) { return SdMan.rmdir(path); }
bool HalStorage::openFileForRead(const char* moduleName, const char* path, File& file) {
return SdMan.openFileForRead(moduleName, path, file);
}
bool HalStorage::openFileForRead(const char* moduleName, const std::string& path, File& file) {
return openFileForRead(moduleName, path.c_str(), file);
}
bool HalStorage::openFileForRead(const char* moduleName, const String& path, File& file) {
return openFileForRead(moduleName, path.c_str(), file);
}
bool HalStorage::openFileForWrite(const char* moduleName, const char* path, File& file) {
return SdMan.openFileForWrite(moduleName, path, file);
}
bool HalStorage::openFileForWrite(const char* moduleName, const std::string& path, File& file) {
return openFileForWrite(moduleName, path.c_str(), file);
}
bool HalStorage::openFileForWrite(const char* moduleName, const String& path, File& file) {
return openFileForWrite(moduleName, path.c_str(), file);
}
bool HalStorage::removeDir(const char* path) { return SdMan.removeDir(path); }

51
lib/hal/HalStorage.h Normal file
View File

@ -0,0 +1,51 @@
#pragma once
#include <SDCardManager.h>
#include <vector>
using File = FsFile;
class HalStorage {
public:
HalStorage();
bool begin();
bool ready() const;
std::vector<String> listFiles(const char* path = "/", int maxFiles = 200);
// Read the entire file at `path` into a String. Returns empty string on failure.
String readFile(const char* path);
// Low-memory helpers:
// Stream the file contents to a `Print` (e.g. `Serial`, or any `Print`-derived object).
// Returns true on success, false on failure.
bool readFileToStream(const char* path, Print& out, size_t chunkSize = 256);
// Read up to `bufferSize-1` bytes into `buffer`, null-terminating it. Returns bytes read.
size_t readFileToBuffer(const char* path, char* buffer, size_t bufferSize, size_t maxBytes = 0);
// Write a string to `path` on the SD card. Overwrites existing file.
// Returns true on success.
bool writeFile(const char* path, const String& content);
// Ensure a directory exists, creating it if necessary. Returns true on success.
bool ensureDirectoryExists(const char* path);
File open(const char* path, const oflag_t oflag = O_RDONLY);
bool mkdir(const char* path, const bool pFlag = true);
bool exists(const char* path);
bool remove(const char* path);
bool rmdir(const char* path);
bool openFileForRead(const char* moduleName, const char* path, File& file);
bool openFileForRead(const char* moduleName, const std::string& path, File& file);
bool openFileForRead(const char* moduleName, const String& path, File& file);
bool openFileForWrite(const char* moduleName, const char* path, File& file);
bool openFileForWrite(const char* moduleName, const std::string& path, File& file);
bool openFileForWrite(const char* moduleName, const String& path, File& file);
bool removeDir(const char* path);
static HalStorage& getInstance() { return instance; }
private:
static HalStorage instance;
bool initialized = false;
};
#define Storage HalStorage::getInstance()

View File

@ -1,7 +1,7 @@
#include "CrossPointSettings.h" #include "CrossPointSettings.h"
#include <HalStorage.h>
#include <HardwareSerial.h> #include <HardwareSerial.h>
#include <SDCardManager.h>
#include <Serialization.h> #include <Serialization.h>
#include <cstring> #include <cstring>
@ -11,7 +11,7 @@
// Initialize the static instance // Initialize the static instance
CrossPointSettings CrossPointSettings::instance; CrossPointSettings CrossPointSettings::instance;
void readAndValidate(FsFile& file, uint8_t& member, const uint8_t maxValue) { void readAndValidate(File& file, uint8_t& member, const uint8_t maxValue) {
uint8_t tempValue; uint8_t tempValue;
serialization::readPod(file, tempValue); serialization::readPod(file, tempValue);
if (tempValue < maxValue) { if (tempValue < maxValue) {
@ -28,10 +28,10 @@ constexpr char SETTINGS_FILE[] = "/.crosspoint/settings.bin";
bool CrossPointSettings::saveToFile() const { bool CrossPointSettings::saveToFile() const {
// Make sure the directory exists // Make sure the directory exists
SdMan.mkdir("/.crosspoint"); Storage.mkdir("/.crosspoint");
FsFile outputFile; File outputFile;
if (!SdMan.openFileForWrite("CPS", SETTINGS_FILE, outputFile)) { if (!Storage.openFileForWrite("CPS", SETTINGS_FILE, outputFile)) {
return false; return false;
} }
@ -68,8 +68,8 @@ bool CrossPointSettings::saveToFile() const {
} }
bool CrossPointSettings::loadFromFile() { bool CrossPointSettings::loadFromFile() {
FsFile inputFile; File inputFile;
if (!SdMan.openFileForRead("CPS", SETTINGS_FILE, inputFile)) { if (!Storage.openFileForRead("CPS", SETTINGS_FILE, inputFile)) {
return false; return false;
} }

View File

@ -1,7 +1,7 @@
#include "CrossPointState.h" #include "CrossPointState.h"
#include <HalStorage.h>
#include <HardwareSerial.h> #include <HardwareSerial.h>
#include <SDCardManager.h>
#include <Serialization.h> #include <Serialization.h>
namespace { namespace {
@ -12,8 +12,8 @@ constexpr char STATE_FILE[] = "/.crosspoint/state.bin";
CrossPointState CrossPointState::instance; CrossPointState CrossPointState::instance;
bool CrossPointState::saveToFile() const { bool CrossPointState::saveToFile() const {
FsFile outputFile; File outputFile;
if (!SdMan.openFileForWrite("CPS", STATE_FILE, outputFile)) { if (!Storage.openFileForWrite("CPS", STATE_FILE, outputFile)) {
return false; return false;
} }
@ -25,8 +25,8 @@ bool CrossPointState::saveToFile() const {
} }
bool CrossPointState::loadFromFile() { bool CrossPointState::loadFromFile() {
FsFile inputFile; File inputFile;
if (!SdMan.openFileForRead("CPS", STATE_FILE, inputFile)) { if (!Storage.openFileForRead("CPS", STATE_FILE, inputFile)) {
return false; return false;
} }

View File

@ -1,7 +1,7 @@
#include "RecentBooksStore.h" #include "RecentBooksStore.h"
#include <HalStorage.h>
#include <HardwareSerial.h> #include <HardwareSerial.h>
#include <SDCardManager.h>
#include <Serialization.h> #include <Serialization.h>
#include <algorithm> #include <algorithm>
@ -35,10 +35,10 @@ void RecentBooksStore::addBook(const std::string& path, const std::string& title
bool RecentBooksStore::saveToFile() const { bool RecentBooksStore::saveToFile() const {
// Make sure the directory exists // Make sure the directory exists
SdMan.mkdir("/.crosspoint"); Storage.mkdir("/.crosspoint");
FsFile outputFile; File outputFile;
if (!SdMan.openFileForWrite("RBS", RECENT_BOOKS_FILE, outputFile)) { if (!Storage.openFileForWrite("RBS", RECENT_BOOKS_FILE, outputFile)) {
return false; return false;
} }
@ -58,8 +58,8 @@ bool RecentBooksStore::saveToFile() const {
} }
bool RecentBooksStore::loadFromFile() { bool RecentBooksStore::loadFromFile() {
FsFile inputFile; File inputFile;
if (!SdMan.openFileForRead("RBS", RECENT_BOOKS_FILE, inputFile)) { if (!Storage.openFileForRead("RBS", RECENT_BOOKS_FILE, inputFile)) {
return false; return false;
} }

View File

@ -1,7 +1,7 @@
#include "WifiCredentialStore.h" #include "WifiCredentialStore.h"
#include <HalStorage.h>
#include <HardwareSerial.h> #include <HardwareSerial.h>
#include <SDCardManager.h>
#include <Serialization.h> #include <Serialization.h>
// Initialize the static instance // Initialize the static instance
@ -29,10 +29,10 @@ void WifiCredentialStore::obfuscate(std::string& data) const {
bool WifiCredentialStore::saveToFile() const { bool WifiCredentialStore::saveToFile() const {
// Make sure the directory exists // Make sure the directory exists
SdMan.mkdir("/.crosspoint"); Storage.mkdir("/.crosspoint");
FsFile file; File file;
if (!SdMan.openFileForWrite("WCS", WIFI_FILE, file)) { if (!Storage.openFileForWrite("WCS", WIFI_FILE, file)) {
return false; return false;
} }
@ -59,8 +59,8 @@ bool WifiCredentialStore::saveToFile() const {
} }
bool WifiCredentialStore::loadFromFile() { bool WifiCredentialStore::loadFromFile() {
FsFile file; File file;
if (!SdMan.openFileForRead("WCS", WIFI_FILE, file)) { if (!Storage.openFileForRead("WCS", WIFI_FILE, file)) {
return false; return false;
} }

View File

@ -2,7 +2,7 @@
#include <Epub.h> #include <Epub.h>
#include <GfxRenderer.h> #include <GfxRenderer.h>
#include <SDCardManager.h> #include <HalStorage.h>
#include <Txt.h> #include <Txt.h>
#include <Xtc.h> #include <Xtc.h>
@ -35,7 +35,7 @@ void SleepActivity::onEnter() {
void SleepActivity::renderCustomSleepScreen() const { void SleepActivity::renderCustomSleepScreen() const {
// Check if we have a /sleep directory // Check if we have a /sleep directory
auto dir = SdMan.open("/sleep"); auto dir = Storage.open("/sleep");
if (dir && dir.isDirectory()) { if (dir && dir.isDirectory()) {
std::vector<std::string> files; std::vector<std::string> files;
char name[500]; char name[500];
@ -77,8 +77,8 @@ void SleepActivity::renderCustomSleepScreen() const {
APP_STATE.lastSleepImage = randomFileIndex; APP_STATE.lastSleepImage = randomFileIndex;
APP_STATE.saveToFile(); APP_STATE.saveToFile();
const auto filename = "/sleep/" + files[randomFileIndex]; const auto filename = "/sleep/" + files[randomFileIndex];
FsFile file; File file;
if (SdMan.openFileForRead("SLP", filename, file)) { if (Storage.openFileForRead("SLP", filename, file)) {
Serial.printf("[%lu] [SLP] Randomly loading: /sleep/%s\n", millis(), files[randomFileIndex].c_str()); Serial.printf("[%lu] [SLP] Randomly loading: /sleep/%s\n", millis(), files[randomFileIndex].c_str());
delay(100); delay(100);
Bitmap bitmap(file, true); Bitmap bitmap(file, true);
@ -94,8 +94,8 @@ void SleepActivity::renderCustomSleepScreen() const {
// Look for sleep.bmp on the root of the sd card to determine if we should // 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. // render a custom sleep screen instead of the default.
FsFile file; File file;
if (SdMan.openFileForRead("SLP", "/sleep.bmp", file)) { if (Storage.openFileForRead("SLP", "/sleep.bmp", file)) {
Bitmap bitmap(file, true); Bitmap bitmap(file, true);
if (bitmap.parseHeaders() == BmpReaderError::Ok) { if (bitmap.parseHeaders() == BmpReaderError::Ok) {
Serial.printf("[%lu] [SLP] Loading: /sleep.bmp\n", millis()); Serial.printf("[%lu] [SLP] Loading: /sleep.bmp\n", millis());
@ -253,8 +253,8 @@ void SleepActivity::renderCoverSleepScreen() const {
return renderDefaultSleepScreen(); return renderDefaultSleepScreen();
} }
FsFile file; File file;
if (SdMan.openFileForRead("SLP", coverBmpPath, file)) { if (Storage.openFileForRead("SLP", coverBmpPath, file)) {
Bitmap bitmap(file); Bitmap bitmap(file);
if (bitmap.parseHeaders() == BmpReaderError::Ok) { if (bitmap.parseHeaders() == BmpReaderError::Ok) {
Serial.printf("[SLP] Rendering sleep cover: %s\n", coverBmpPath); Serial.printf("[SLP] Rendering sleep cover: %s\n", coverBmpPath);

View File

@ -3,7 +3,7 @@
#include <Bitmap.h> #include <Bitmap.h>
#include <Epub.h> #include <Epub.h>
#include <GfxRenderer.h> #include <GfxRenderer.h>
#include <SDCardManager.h> #include <HalStorage.h>
#include <Utf8.h> #include <Utf8.h>
#include <Xtc.h> #include <Xtc.h>
@ -36,7 +36,7 @@ void HomeActivity::onEnter() {
renderingMutex = xSemaphoreCreateMutex(); renderingMutex = xSemaphoreCreateMutex();
// Check if we have a book to continue reading // Check if we have a book to continue reading
hasContinueReading = !APP_STATE.openEpubPath.empty() && SdMan.exists(APP_STATE.openEpubPath.c_str()); hasContinueReading = !APP_STATE.openEpubPath.empty() && Storage.exists(APP_STATE.openEpubPath.c_str());
// Check if OPDS browser URL is configured // Check if OPDS browser URL is configured
hasOpdsUrl = strlen(SETTINGS.opdsServerUrl) > 0; hasOpdsUrl = strlen(SETTINGS.opdsServerUrl) > 0;
@ -242,8 +242,8 @@ void HomeActivity::render() {
// Only load from SD on first render, then use stored buffer // Only load from SD on first render, then use stored buffer
if (hasContinueReading && hasCoverImage && !coverBmpPath.empty() && !coverRendered) { if (hasContinueReading && hasCoverImage && !coverBmpPath.empty() && !coverRendered) {
// First time: load cover from SD and render // First time: load cover from SD and render
FsFile file; File file;
if (SdMan.openFileForRead("HOME", coverBmpPath, file)) { if (Storage.openFileForRead("HOME", coverBmpPath, file)) {
Bitmap bitmap(file); Bitmap bitmap(file);
if (bitmap.parseHeaders() == BmpReaderError::Ok) { if (bitmap.parseHeaders() == BmpReaderError::Ok) {
// Calculate position to center image within the book card // Calculate position to center image within the book card

View File

@ -1,7 +1,7 @@
#include "MyLibraryActivity.h" #include "MyLibraryActivity.h"
#include <GfxRenderer.h> #include <GfxRenderer.h>
#include <SDCardManager.h> #include <HalStorage.h>
#include <algorithm> #include <algorithm>
@ -72,7 +72,7 @@ void MyLibraryActivity::loadRecentBooks() {
for (const auto& book : books) { for (const auto& book : books) {
// Skip if file no longer exists // Skip if file no longer exists
if (!SdMan.exists(book.path.c_str())) { if (!Storage.exists(book.path.c_str())) {
continue; continue;
} }
recentBooks.push_back(book); recentBooks.push_back(book);
@ -82,7 +82,7 @@ void MyLibraryActivity::loadRecentBooks() {
void MyLibraryActivity::loadFiles() { void MyLibraryActivity::loadFiles() {
files.clear(); files.clear();
auto root = SdMan.open(basepath.c_str()); auto root = Storage.open(basepath.c_str());
if (!root || !root.isDirectory()) { if (!root || !root.isDirectory()) {
if (root) root.close(); if (root) root.close();
return; return;

View File

@ -3,7 +3,7 @@
#include <Epub/Page.h> #include <Epub/Page.h>
#include <FsHelpers.h> #include <FsHelpers.h>
#include <GfxRenderer.h> #include <GfxRenderer.h>
#include <SDCardManager.h> #include <HalStorage.h>
#include "CrossPointSettings.h" #include "CrossPointSettings.h"
#include "CrossPointState.h" #include "CrossPointState.h"
@ -56,8 +56,8 @@ void EpubReaderActivity::onEnter() {
epub->setupCacheDir(); epub->setupCacheDir();
FsFile f; File f;
if (SdMan.openFileForRead("ERS", epub->getCachePath() + "/progress.bin", f)) { if (Storage.openFileForRead("ERS", epub->getCachePath() + "/progress.bin", f)) {
uint8_t data[6]; uint8_t data[6];
int dataSize = f.read(data, 6); int dataSize = f.read(data, 6);
if (dataSize == 4 || dataSize == 6) { if (dataSize == 4 || dataSize == 6) {
@ -435,7 +435,7 @@ void EpubReaderActivity::renderScreen() {
void EpubReaderActivity::saveProgress(int spineIndex, int currentPage, int pageCount) { void EpubReaderActivity::saveProgress(int spineIndex, int currentPage, int pageCount) {
FsFile f; FsFile f;
if (SdMan.openFileForWrite("ERS", epub->getCachePath() + "/progress.bin", f)) { if (Storage.openFileForWrite("ERS", epub->getCachePath() + "/progress.bin", f)) {
uint8_t data[6]; uint8_t data[6];
data[0] = currentSpineIndex & 0xFF; data[0] = currentSpineIndex & 0xFF;
data[1] = (currentSpineIndex >> 8) & 0xFF; data[1] = (currentSpineIndex >> 8) & 0xFF;

View File

@ -1,5 +1,7 @@
#include "ReaderActivity.h" #include "ReaderActivity.h"
#include <HalStorage.h>
#include "Epub.h" #include "Epub.h"
#include "EpubReaderActivity.h" #include "EpubReaderActivity.h"
#include "Txt.h" #include "Txt.h"
@ -27,7 +29,7 @@ bool ReaderActivity::isTxtFile(const std::string& path) {
} }
std::unique_ptr<Epub> ReaderActivity::loadEpub(const std::string& path) { std::unique_ptr<Epub> ReaderActivity::loadEpub(const std::string& path) {
if (!SdMan.exists(path.c_str())) { if (!Storage.exists(path.c_str())) {
Serial.printf("[%lu] [ ] File does not exist: %s\n", millis(), path.c_str()); Serial.printf("[%lu] [ ] File does not exist: %s\n", millis(), path.c_str());
return nullptr; return nullptr;
} }
@ -42,7 +44,7 @@ std::unique_ptr<Epub> ReaderActivity::loadEpub(const std::string& path) {
} }
std::unique_ptr<Xtc> ReaderActivity::loadXtc(const std::string& path) { std::unique_ptr<Xtc> ReaderActivity::loadXtc(const std::string& path) {
if (!SdMan.exists(path.c_str())) { if (!Storage.exists(path.c_str())) {
Serial.printf("[%lu] [ ] File does not exist: %s\n", millis(), path.c_str()); Serial.printf("[%lu] [ ] File does not exist: %s\n", millis(), path.c_str());
return nullptr; return nullptr;
} }
@ -57,7 +59,7 @@ std::unique_ptr<Xtc> ReaderActivity::loadXtc(const std::string& path) {
} }
std::unique_ptr<Txt> ReaderActivity::loadTxt(const std::string& path) { std::unique_ptr<Txt> ReaderActivity::loadTxt(const std::string& path) {
if (!SdMan.exists(path.c_str())) { if (!Storage.exists(path.c_str())) {
Serial.printf("[%lu] [ ] File does not exist: %s\n", millis(), path.c_str()); Serial.printf("[%lu] [ ] File does not exist: %s\n", millis(), path.c_str());
return nullptr; return nullptr;
} }

View File

@ -1,7 +1,7 @@
#include "TxtReaderActivity.h" #include "TxtReaderActivity.h"
#include <GfxRenderer.h> #include <GfxRenderer.h>
#include <SDCardManager.h> #include <HalStorage.h>
#include <Serialization.h> #include <Serialization.h>
#include <Utf8.h> #include <Utf8.h>
@ -543,8 +543,8 @@ void TxtReaderActivity::renderStatusBar(const int orientedMarginRight, const int
} }
void TxtReaderActivity::saveProgress() const { void TxtReaderActivity::saveProgress() const {
FsFile f; File f;
if (SdMan.openFileForWrite("TRS", txt->getCachePath() + "/progress.bin", f)) { if (Storage.openFileForWrite("TRS", txt->getCachePath() + "/progress.bin", f)) {
uint8_t data[4]; uint8_t data[4];
data[0] = currentPage & 0xFF; data[0] = currentPage & 0xFF;
data[1] = (currentPage >> 8) & 0xFF; data[1] = (currentPage >> 8) & 0xFF;
@ -556,8 +556,8 @@ void TxtReaderActivity::saveProgress() const {
} }
void TxtReaderActivity::loadProgress() { void TxtReaderActivity::loadProgress() {
FsFile f; File f;
if (SdMan.openFileForRead("TRS", txt->getCachePath() + "/progress.bin", f)) { if (Storage.openFileForRead("TRS", txt->getCachePath() + "/progress.bin", f)) {
uint8_t data[4]; uint8_t data[4];
if (f.read(data, 4) == 4) { if (f.read(data, 4) == 4) {
currentPage = data[0] + (data[1] << 8); currentPage = data[0] + (data[1] << 8);
@ -587,8 +587,8 @@ bool TxtReaderActivity::loadPageIndexCache() {
// - N * uint32_t: page offsets // - N * uint32_t: page offsets
std::string cachePath = txt->getCachePath() + "/index.bin"; std::string cachePath = txt->getCachePath() + "/index.bin";
FsFile f; File f;
if (!SdMan.openFileForRead("TRS", cachePath, f)) { if (!Storage.openFileForRead("TRS", cachePath, f)) {
Serial.printf("[%lu] [TRS] No page index cache found\n", millis()); Serial.printf("[%lu] [TRS] No page index cache found\n", millis());
return false; return false;
} }
@ -679,8 +679,8 @@ bool TxtReaderActivity::loadPageIndexCache() {
void TxtReaderActivity::savePageIndexCache() const { void TxtReaderActivity::savePageIndexCache() const {
std::string cachePath = txt->getCachePath() + "/index.bin"; std::string cachePath = txt->getCachePath() + "/index.bin";
FsFile f; File f;
if (!SdMan.openFileForWrite("TRS", cachePath, f)) { if (!Storage.openFileForWrite("TRS", cachePath, f)) {
Serial.printf("[%lu] [TRS] Failed to save page index cache\n", millis()); Serial.printf("[%lu] [TRS] Failed to save page index cache\n", millis());
return; return;
} }

View File

@ -9,7 +9,7 @@
#include <FsHelpers.h> #include <FsHelpers.h>
#include <GfxRenderer.h> #include <GfxRenderer.h>
#include <SDCardManager.h> #include <HalStorage.h>
#include "CrossPointSettings.h" #include "CrossPointSettings.h"
#include "CrossPointState.h" #include "CrossPointState.h"
@ -368,8 +368,8 @@ void XtcReaderActivity::renderPage() {
} }
void XtcReaderActivity::saveProgress() const { void XtcReaderActivity::saveProgress() const {
FsFile f; File f;
if (SdMan.openFileForWrite("XTR", xtc->getCachePath() + "/progress.bin", f)) { if (Storage.openFileForWrite("XTR", xtc->getCachePath() + "/progress.bin", f)) {
uint8_t data[4]; uint8_t data[4];
data[0] = currentPage & 0xFF; data[0] = currentPage & 0xFF;
data[1] = (currentPage >> 8) & 0xFF; data[1] = (currentPage >> 8) & 0xFF;
@ -381,8 +381,8 @@ void XtcReaderActivity::saveProgress() const {
} }
void XtcReaderActivity::loadProgress() { void XtcReaderActivity::loadProgress() {
FsFile f; File f;
if (SdMan.openFileForRead("XTR", xtc->getCachePath() + "/progress.bin", f)) { if (Storage.openFileForRead("XTR", xtc->getCachePath() + "/progress.bin", f)) {
uint8_t data[4]; uint8_t data[4];
if (f.read(data, 4) == 4) { if (f.read(data, 4) == 4) {
currentPage = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); currentPage = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);

View File

@ -1,8 +1,8 @@
#include "ClearCacheActivity.h" #include "ClearCacheActivity.h"
#include <GfxRenderer.h> #include <GfxRenderer.h>
#include <HalStorage.h>
#include <HardwareSerial.h> #include <HardwareSerial.h>
#include <SDCardManager.h>
#include "MappedInputManager.h" #include "MappedInputManager.h"
#include "fontIds.h" #include "fontIds.h"
@ -106,7 +106,7 @@ void ClearCacheActivity::clearCache() {
Serial.printf("[%lu] [CLEAR_CACHE] Clearing cache...\n", millis()); Serial.printf("[%lu] [CLEAR_CACHE] Clearing cache...\n", millis());
// Open .crosspoint directory // Open .crosspoint directory
auto root = SdMan.open("/.crosspoint"); auto root = Storage.open("/.crosspoint");
if (!root || !root.isDirectory()) { if (!root || !root.isDirectory()) {
Serial.printf("[%lu] [CLEAR_CACHE] Failed to open cache directory\n", millis()); Serial.printf("[%lu] [CLEAR_CACHE] Failed to open cache directory\n", millis());
if (root) root.close(); if (root) root.close();
@ -131,7 +131,7 @@ void ClearCacheActivity::clearCache() {
file.close(); // Close before attempting to delete file.close(); // Close before attempting to delete
if (SdMan.removeDir(fullPath.c_str())) { if (Storage.removeDir(fullPath.c_str())) {
clearedCount++; clearedCount++;
} else { } else {
Serial.printf("[%lu] [CLEAR_CACHE] Failed to remove: %s\n", millis(), fullPath.c_str()); Serial.printf("[%lu] [CLEAR_CACHE] Failed to remove: %s\n", millis(), fullPath.c_str());

View File

@ -3,7 +3,7 @@
#include <GfxRenderer.h> #include <GfxRenderer.h>
#include <HalDisplay.h> #include <HalDisplay.h>
#include <HalGPIO.h> #include <HalGPIO.h>
#include <SDCardManager.h> #include <HalStorage.h>
#include <SPI.h> #include <SPI.h>
#include <builtinFonts/all.h> #include <builtinFonts/all.h>
@ -283,7 +283,7 @@ void setup() {
// SD Card Initialization // SD Card Initialization
// We need 6 open files concurrently when parsing a new chapter // We need 6 open files concurrently when parsing a new chapter
if (!SdMan.begin()) { if (!Storage.begin()) {
Serial.printf("[%lu] [ ] SD card initialization failed\n", millis()); Serial.printf("[%lu] [ ] SD card initialization failed\n", millis());
setupDisplayAndFonts(); setupDisplayAndFonts();
exitActivity(); exitActivity();

View File

@ -3,7 +3,7 @@
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <Epub.h> #include <Epub.h>
#include <FsHelpers.h> #include <FsHelpers.h>
#include <SDCardManager.h> #include <HalStorage.h>
#include <WiFi.h> #include <WiFi.h>
#include <esp_task_wdt.h> #include <esp_task_wdt.h>
@ -25,7 +25,7 @@ constexpr uint16_t LOCAL_UDP_PORT = 8134;
CrossPointWebServer* wsInstance = nullptr; CrossPointWebServer* wsInstance = nullptr;
// WebSocket upload state // WebSocket upload state
FsFile wsUploadFile; File wsUploadFile;
String wsUploadFileName; String wsUploadFileName;
String wsUploadPath; String wsUploadPath;
size_t wsUploadSize = 0; size_t wsUploadSize = 0;
@ -280,7 +280,7 @@ void CrossPointWebServer::handleStatus() const {
} }
void CrossPointWebServer::scanFiles(const char* path, const std::function<void(FileInfo)>& callback) const { void CrossPointWebServer::scanFiles(const char* path, const std::function<void(FileInfo)>& callback) const {
FsFile root = SdMan.open(path); File root = Storage.open(path);
if (!root) { if (!root) {
Serial.printf("[%lu] [WEB] Failed to open directory: %s\n", millis(), path); Serial.printf("[%lu] [WEB] Failed to open directory: %s\n", millis(), path);
return; return;
@ -294,7 +294,7 @@ void CrossPointWebServer::scanFiles(const char* path, const std::function<void(F
Serial.printf("[%lu] [WEB] Scanning files in: %s\n", millis(), path); Serial.printf("[%lu] [WEB] Scanning files in: %s\n", millis(), path);
FsFile file = root.openNextFile(); File file = root.openNextFile();
char name[500]; char name[500];
while (file) { while (file) {
file.getName(name, sizeof(name)); file.getName(name, sizeof(name));
@ -422,12 +422,12 @@ void CrossPointWebServer::handleDownload() const {
} }
} }
if (!SdMan.exists(itemPath.c_str())) { if (!Storage.exists(itemPath.c_str())) {
server->send(404, "text/plain", "Item not found"); server->send(404, "text/plain", "Item not found");
return; return;
} }
FsFile file = SdMan.open(itemPath.c_str()); File file = Storage.open(itemPath.c_str());
if (!file) { if (!file) {
server->send(500, "text/plain", "Failed to open file"); server->send(500, "text/plain", "Failed to open file");
return; return;
@ -459,7 +459,7 @@ void CrossPointWebServer::handleDownload() const {
} }
// Static variables for upload handling // Static variables for upload handling
static FsFile uploadFile; static File uploadFile;
static String uploadFileName; static String uploadFileName;
static String uploadPath = "/"; static String uploadPath = "/";
static size_t uploadSize = 0; static size_t uploadSize = 0;
@ -553,15 +553,15 @@ void CrossPointWebServer::handleUpload() const {
// Check if file already exists - SD operations can be slow // Check if file already exists - SD operations can be slow
esp_task_wdt_reset(); esp_task_wdt_reset();
if (SdMan.exists(filePath.c_str())) { if (Storage.exists(filePath.c_str())) {
Serial.printf("[%lu] [WEB] [UPLOAD] Overwriting existing file: %s\n", millis(), filePath.c_str()); Serial.printf("[%lu] [WEB] [UPLOAD] Overwriting existing file: %s\n", millis(), filePath.c_str());
esp_task_wdt_reset(); esp_task_wdt_reset();
SdMan.remove(filePath.c_str()); Storage.remove(filePath.c_str());
} }
// Open file for writing - this can be slow due to FAT cluster allocation // Open file for writing - this can be slow due to FAT cluster allocation
esp_task_wdt_reset(); esp_task_wdt_reset();
if (!SdMan.openFileForWrite("WEB", filePath, uploadFile)) { if (!Storage.openFileForWrite("WEB", filePath, uploadFile)) {
uploadError = "Failed to create file on SD card"; uploadError = "Failed to create file on SD card";
Serial.printf("[%lu] [WEB] [UPLOAD] FAILED to create file: %s\n", millis(), filePath.c_str()); Serial.printf("[%lu] [WEB] [UPLOAD] FAILED to create file: %s\n", millis(), filePath.c_str());
return; return;
@ -639,7 +639,7 @@ void CrossPointWebServer::handleUpload() const {
String filePath = uploadPath; String filePath = uploadPath;
if (!filePath.endsWith("/")) filePath += "/"; if (!filePath.endsWith("/")) filePath += "/";
filePath += uploadFileName; filePath += uploadFileName;
SdMan.remove(filePath.c_str()); Storage.remove(filePath.c_str());
} }
uploadError = "Upload aborted"; uploadError = "Upload aborted";
Serial.printf("[%lu] [WEB] Upload aborted\n", millis()); Serial.printf("[%lu] [WEB] Upload aborted\n", millis());
@ -690,13 +690,13 @@ void CrossPointWebServer::handleCreateFolder() const {
Serial.printf("[%lu] [WEB] Creating folder: %s\n", millis(), folderPath.c_str()); Serial.printf("[%lu] [WEB] Creating folder: %s\n", millis(), folderPath.c_str());
// Check if already exists // Check if already exists
if (SdMan.exists(folderPath.c_str())) { if (Storage.exists(folderPath.c_str())) {
server->send(400, "text/plain", "Folder already exists"); server->send(400, "text/plain", "Folder already exists");
return; return;
} }
// Create the folder // Create the folder
if (SdMan.mkdir(folderPath.c_str())) { if (Storage.mkdir(folderPath.c_str())) {
Serial.printf("[%lu] [WEB] Folder created successfully: %s\n", millis(), folderPath.c_str()); Serial.printf("[%lu] [WEB] Folder created successfully: %s\n", millis(), folderPath.c_str());
server->send(200, "text/plain", "Folder created: " + folderName); server->send(200, "text/plain", "Folder created: " + folderName);
} else { } else {
@ -746,7 +746,7 @@ void CrossPointWebServer::handleDelete() const {
} }
// Check if item exists // Check if item exists
if (!SdMan.exists(itemPath.c_str())) { if (!Storage.exists(itemPath.c_str())) {
Serial.printf("[%lu] [WEB] Delete failed - item not found: %s\n", millis(), itemPath.c_str()); Serial.printf("[%lu] [WEB] Delete failed - item not found: %s\n", millis(), itemPath.c_str());
server->send(404, "text/plain", "Item not found"); server->send(404, "text/plain", "Item not found");
return; return;
@ -758,10 +758,10 @@ void CrossPointWebServer::handleDelete() const {
if (itemType == "folder") { if (itemType == "folder") {
// For folders, try to remove (will fail if not empty) // For folders, try to remove (will fail if not empty)
FsFile dir = SdMan.open(itemPath.c_str()); File dir = Storage.open(itemPath.c_str());
if (dir && dir.isDirectory()) { if (dir && dir.isDirectory()) {
// Check if folder is empty // Check if folder is empty
FsFile entry = dir.openNextFile(); File entry = dir.openNextFile();
if (entry) { if (entry) {
// Folder is not empty // Folder is not empty
entry.close(); entry.close();
@ -772,10 +772,10 @@ void CrossPointWebServer::handleDelete() const {
} }
dir.close(); dir.close();
} }
success = SdMan.rmdir(itemPath.c_str()); success = Storage.rmdir(itemPath.c_str());
} else { } else {
// For files, use remove // For files, use remove
success = SdMan.remove(itemPath.c_str()); success = Storage.remove(itemPath.c_str());
} }
if (success) { if (success) {
@ -811,7 +811,7 @@ void CrossPointWebServer::onWebSocketEvent(uint8_t num, WStype_t type, uint8_t*
String filePath = wsUploadPath; String filePath = wsUploadPath;
if (!filePath.endsWith("/")) filePath += "/"; if (!filePath.endsWith("/")) filePath += "/";
filePath += wsUploadFileName; filePath += wsUploadFileName;
SdMan.remove(filePath.c_str()); Storage.remove(filePath.c_str());
Serial.printf("[%lu] [WS] Deleted incomplete upload: %s\n", millis(), filePath.c_str()); Serial.printf("[%lu] [WS] Deleted incomplete upload: %s\n", millis(), filePath.c_str());
} }
wsUploadInProgress = false; wsUploadInProgress = false;
@ -855,13 +855,13 @@ void CrossPointWebServer::onWebSocketEvent(uint8_t num, WStype_t type, uint8_t*
// Check if file exists and remove it // Check if file exists and remove it
esp_task_wdt_reset(); esp_task_wdt_reset();
if (SdMan.exists(filePath.c_str())) { if (Storage.exists(filePath.c_str())) {
SdMan.remove(filePath.c_str()); Storage.remove(filePath.c_str());
} }
// Open file for writing // Open file for writing
esp_task_wdt_reset(); esp_task_wdt_reset();
if (!SdMan.openFileForWrite("WS", filePath, wsUploadFile)) { if (!Storage.openFileForWrite("WS", filePath, wsUploadFile)) {
wsServer->sendTXT(num, "ERROR:Failed to create file"); wsServer->sendTXT(num, "ERROR:Failed to create file");
wsUploadInProgress = false; wsUploadInProgress = false;
return; return;

View File

@ -100,13 +100,13 @@ HttpDownloader::DownloadError HttpDownloader::downloadToFile(const std::string&
Serial.printf("[%lu] [HTTP] Content-Length: %zu\n", millis(), contentLength); Serial.printf("[%lu] [HTTP] Content-Length: %zu\n", millis(), contentLength);
// Remove existing file if present // Remove existing file if present
if (SdMan.exists(destPath.c_str())) { if (Storage.exists(destPath.c_str())) {
SdMan.remove(destPath.c_str()); Storage.remove(destPath.c_str());
} }
// Open file for writing // Open file for writing
FsFile file; File file;
if (!SdMan.openFileForWrite("HTTP", destPath.c_str(), file)) { if (!Storage.openFileForWrite("HTTP", destPath.c_str(), file)) {
Serial.printf("[%lu] [HTTP] Failed to open file for writing\n", millis()); Serial.printf("[%lu] [HTTP] Failed to open file for writing\n", millis());
http.end(); http.end();
return FILE_ERROR; return FILE_ERROR;
@ -117,7 +117,7 @@ HttpDownloader::DownloadError HttpDownloader::downloadToFile(const std::string&
if (!stream) { if (!stream) {
Serial.printf("[%lu] [HTTP] Failed to get stream\n", millis()); Serial.printf("[%lu] [HTTP] Failed to get stream\n", millis());
file.close(); file.close();
SdMan.remove(destPath.c_str()); Storage.remove(destPath.c_str());
http.end(); http.end();
return HTTP_ERROR; return HTTP_ERROR;
} }
@ -145,7 +145,7 @@ HttpDownloader::DownloadError HttpDownloader::downloadToFile(const std::string&
if (written != bytesRead) { if (written != bytesRead) {
Serial.printf("[%lu] [HTTP] Write failed: wrote %zu of %zu bytes\n", millis(), written, bytesRead); Serial.printf("[%lu] [HTTP] Write failed: wrote %zu of %zu bytes\n", millis(), written, bytesRead);
file.close(); file.close();
SdMan.remove(destPath.c_str()); Storage.remove(destPath.c_str());
http.end(); http.end();
return FILE_ERROR; return FILE_ERROR;
} }
@ -165,7 +165,7 @@ HttpDownloader::DownloadError HttpDownloader::downloadToFile(const std::string&
// Verify download size if known // Verify download size if known
if (contentLength > 0 && downloaded != contentLength) { if (contentLength > 0 && downloaded != contentLength) {
Serial.printf("[%lu] [HTTP] Size mismatch: got %zu, expected %zu\n", millis(), downloaded, contentLength); Serial.printf("[%lu] [HTTP] Size mismatch: got %zu, expected %zu\n", millis(), downloaded, contentLength);
SdMan.remove(destPath.c_str()); Storage.remove(destPath.c_str());
return HTTP_ERROR; return HTTP_ERROR;
} }

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#include <SDCardManager.h> #include <HalStorage.h>
#include <functional> #include <functional>
#include <string> #include <string>