Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions libraries/ArduinoStorage/ArduinoStorage.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2024 Arduino SA
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef ARDUINO_STORAGE_H
#define ARDUINO_STORAGE_H

/**
* @brief Arduino Storage Library
*
* This library provides a unified interface for all Arduino storage implementations.
* It defines the base classes and error handling that all storage types (QSPI, SD, Flash, etc.)
* conform to.
*
* Include this header to get access to:
* - StorageError: Error handling class
* - File: Abstract base class for file operations
* - Folder: Abstract base class for folder operations
* - FileMode: Enum for file opening modes
* - FilesystemType: Enum for filesystem types
*
* For specific storage implementations, include their respective headers:
* - QSPIStorage.h: QSPI flash storage
* - SDStorage.h: SD card storage
* - FlashStorage.h: Internal flash storage
*/

#include "StorageCommon.h"
#include "StorageError.h"
#include "StorageFile.h"
#include "StorageFolder.h"

#endif // ARDUINO_STORAGE_H
10 changes: 10 additions & 0 deletions libraries/ArduinoStorage/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# SPDX-License-Identifier: Apache-2.0
zephyr_include_directories(.)

if(NOT DEFINED ARDUINO_BUILD_PATH)
zephyr_sources_ifdef(CONFIG_FILE_SYSTEM
StorageError.cpp
StorageFile.cpp
StorageFolder.cpp
)
endif()
65 changes: 65 additions & 0 deletions libraries/ArduinoStorage/StorageCommon.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2024 Arduino SA
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef ARDUINO_STORAGE_COMMON_H
#define ARDUINO_STORAGE_COMMON_H

#include <Arduino.h>

// File opening modes
enum class FileMode {
READ, // Open for reading, file must exist
WRITE, // Open for writing, creates if doesn't exist, truncates if exists
APPEND, // Open for writing at end, creates if doesn't exist
READ_WRITE, // Open for reading and writing, file must exist
READ_WRITE_CREATE // Open for reading and writing, creates if doesn't exist
};

// Supported filesystem types
enum class FilesystemType {
LITTLEFS, // LittleFS - recommended for flash storage
FAT, // FAT32 - better compatibility, larger overhead
EXT2, // Extended 2 - Linux-style filesystem
AUTO // Auto-detect or use default
};

// Storage information structure
struct StorageInfo {
char mountPoint[64];
FilesystemType fsType;
size_t totalBytes;
size_t usedBytes;
size_t availableBytes;
size_t blockSize;
size_t totalBlocks;
size_t usedBlocks;
bool readOnly;
bool mounted;
};

// Storage health structure
struct StorageHealth {
bool healthy; // Overall health status
uint32_t errorCount; // Number of errors encountered
uint32_t badBlocks; // Number of bad blocks (flash)
uint32_t writeCount; // Total write operations
uint32_t eraseCount; // Total erase operations
float fragmentationPercent; // File system fragmentation
char statusMessage[128]; // Human-readable status
};

// Partition information
struct PartitionInfo {
const char* label; // Partition name/label
size_t offset; // Start offset in bytes
size_t size; // Size in bytes
FilesystemType fsType; // File system type for this partition
};

// Maximum path length
constexpr size_t STORAGE_MAX_PATH_LENGTH = 256;

#endif // ARDUINO_STORAGE_COMMON_H
96 changes: 96 additions & 0 deletions libraries/ArduinoStorage/StorageError.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* Copyright (c) 2024 Arduino SA
*
* SPDX-License-Identifier: Apache-2.0
*/

#include "StorageError.h"
#include <cstring>

StorageError::StorageError() : code_(StorageErrorCode::NONE) {
message_[0] = '\0';
}

StorageErrorCode StorageError::getCode() const {
return code_;
}

const char* StorageError::getMessage() const {
if (message_[0] != '\0') {
return message_;
}

// Return default message based on error code
switch (code_) {
case StorageErrorCode::NONE:
return "No error";
case StorageErrorCode::FILE_NOT_FOUND:
return "File not found";
case StorageErrorCode::FOLDER_NOT_FOUND:
return "Folder not found";
case StorageErrorCode::ALREADY_EXISTS:
return "Already exists";
case StorageErrorCode::INVALID_PATH:
return "Invalid path";
case StorageErrorCode::PERMISSION_DENIED:
return "Permission denied";
case StorageErrorCode::READ_ERROR:
return "Read error";
case StorageErrorCode::WRITE_ERROR:
return "Write error";
case StorageErrorCode::SEEK_ERROR:
return "Seek error";
case StorageErrorCode::OPEN_ERROR:
return "Open error";
case StorageErrorCode::CLOSE_ERROR:
return "Close error";
case StorageErrorCode::STORAGE_FULL:
return "Storage full";
case StorageErrorCode::STORAGE_NOT_MOUNTED:
return "Storage not mounted";
case StorageErrorCode::STORAGE_CORRUPTED:
return "Storage corrupted";
case StorageErrorCode::STORAGE_NOT_FORMATTED:
return "Storage not formatted";
case StorageErrorCode::INVALID_OPERATION:
return "Invalid operation";
case StorageErrorCode::INVALID_MODE:
return "Invalid mode";
case StorageErrorCode::BUFFER_OVERFLOW:
return "Buffer overflow";
case StorageErrorCode::OUT_OF_MEMORY:
return "Out of memory";
case StorageErrorCode::TIMEOUT:
return "Timeout";
case StorageErrorCode::HARDWARE_ERROR:
return "Hardware error";
case StorageErrorCode::NOT_INITIALIZED:
return "Not initialized";
case StorageErrorCode::UNKNOWN_ERROR:
default:
return "Unknown error";
}
}

bool StorageError::hasError() const {
return code_ != StorageErrorCode::NONE;
}

void StorageError::setError(StorageErrorCode code, const char* message) {
code_ = code;
if (message != nullptr) {
strncpy(message_, message, sizeof(message_) - 1);
message_[sizeof(message_) - 1] = '\0';
} else {
message_[0] = '\0';
}
}

void StorageError::clear() {
code_ = StorageErrorCode::NONE;
message_[0] = '\0';
}

StorageError::operator bool() const {
return hasError();
}
71 changes: 71 additions & 0 deletions libraries/ArduinoStorage/StorageError.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2024 Arduino SA
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef ARDUINO_STORAGE_ERROR_H
#define ARDUINO_STORAGE_ERROR_H

#include <Arduino.h>

enum class StorageErrorCode {
NONE = 0,

// File/Folder errors
FILE_NOT_FOUND,
FOLDER_NOT_FOUND,
ALREADY_EXISTS,
INVALID_PATH,
PERMISSION_DENIED,

// I/O errors
READ_ERROR,
WRITE_ERROR,
SEEK_ERROR,
OPEN_ERROR,
CLOSE_ERROR,

// Storage errors
STORAGE_FULL,
STORAGE_NOT_MOUNTED,
STORAGE_CORRUPTED,
STORAGE_NOT_FORMATTED,

// Operation errors
INVALID_OPERATION,
INVALID_MODE,
BUFFER_OVERFLOW,
OUT_OF_MEMORY,
TIMEOUT,

// Hardware errors
HARDWARE_ERROR,
NOT_INITIALIZED,

// Generic
UNKNOWN_ERROR
};

class StorageError {
public:
StorageError();

// Error state
StorageErrorCode getCode() const;
const char* getMessage() const;
bool hasError() const;

// Error setting (for implementations)
void setError(StorageErrorCode code, const char* message = nullptr);
void clear();

// Convenience operators
operator bool() const; // Returns true if error exists

private:
StorageErrorCode code_;
char message_[128];
};

#endif // ARDUINO_STORAGE_ERROR_H
51 changes: 51 additions & 0 deletions libraries/ArduinoStorage/StorageFile.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2024 Arduino SA
*
* SPDX-License-Identifier: Apache-2.0
*/

#include "StorageFile.h"
#include <cstring>

File::File() {
path_[0] = '\0';
}

File::File(const char* path) {
if (path != nullptr) {
strncpy(path_, path, sizeof(path_) - 1);
path_[sizeof(path_) - 1] = '\0';
} else {
path_[0] = '\0';
}
}

File::File(const String& path) {
strncpy(path_, path.c_str(), sizeof(path_) - 1);
path_[sizeof(path_) - 1] = '\0';
}

File::~File() {
}

const char* File::getPath() const {
return path_;
}

String File::getPathAsString() const {
return String(path_);
}

String File::getFilename() const {
const char* lastSep = strrchr(path_, '/');
if (lastSep != nullptr) {
return String(lastSep + 1);
}
return String(path_);
}

void File::setErrorIfNotNull(StorageError* error, StorageErrorCode code, const char* message) {
if (error != nullptr) {
error->setError(code, message);
}
}
Loading
Loading