mirror of
https://github.com/meshtastic/firmware.git
synced 2025-06-21 20:44:47 +00:00

Some checks are pending
CI / setup (check) (push) Waiting to run
CI / setup (esp32) (push) Waiting to run
CI / setup (esp32c3) (push) Waiting to run
CI / setup (esp32c6) (push) Waiting to run
CI / setup (esp32s3) (push) Waiting to run
CI / setup (nrf52840) (push) Waiting to run
CI / setup (rp2040) (push) Waiting to run
CI / setup (stm32) (push) Waiting to run
CI / check (push) Blocked by required conditions
CI / build-esp32 (push) Blocked by required conditions
CI / build-esp32-s3 (push) Blocked by required conditions
CI / build-esp32-c3 (push) Blocked by required conditions
CI / build-esp32-c6 (push) Blocked by required conditions
CI / build-nrf52 (push) Blocked by required conditions
CI / build-rpi2040 (push) Blocked by required conditions
CI / build-stm32 (push) Blocked by required conditions
CI / build-debian-src (push) Waiting to run
CI / package-pio-deps-native-tft (push) Waiting to run
CI / test-native (push) Waiting to run
CI / docker-deb-amd64 (push) Waiting to run
CI / docker-deb-amd64-tft (push) Waiting to run
CI / docker-alp-amd64 (push) Waiting to run
CI / docker-alp-amd64-tft (push) Waiting to run
CI / docker-deb-arm64 (push) Waiting to run
CI / docker-deb-armv7 (push) Waiting to run
CI / gather-artifacts (esp32) (push) Blocked by required conditions
CI / gather-artifacts (esp32c3) (push) Blocked by required conditions
CI / gather-artifacts (esp32c6) (push) Blocked by required conditions
CI / gather-artifacts (esp32s3) (push) Blocked by required conditions
CI / gather-artifacts (nrf52840) (push) Blocked by required conditions
CI / gather-artifacts (rp2040) (push) Blocked by required conditions
CI / gather-artifacts (stm32) (push) Blocked by required conditions
CI / release-artifacts (push) Blocked by required conditions
CI / release-firmware (esp32) (push) Blocked by required conditions
CI / release-firmware (esp32c3) (push) Blocked by required conditions
CI / release-firmware (esp32c6) (push) Blocked by required conditions
CI / release-firmware (esp32s3) (push) Blocked by required conditions
CI / release-firmware (nrf52840) (push) Blocked by required conditions
CI / release-firmware (rp2040) (push) Blocked by required conditions
CI / release-firmware (stm32) (push) Blocked by required conditions
CI / publish-firmware (push) Blocked by required conditions
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
174 lines
4.9 KiB
C++
174 lines
4.9 KiB
C++
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
|
|
|
|
/*
|
|
|
|
Re-usable NicheGraphics tool
|
|
|
|
Save settings / data to flash, without use of the Meshtastic Protobufs
|
|
Avoid bloating everyone's protobuf code for our one-off UI implementations
|
|
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "configuration.h"
|
|
|
|
#include "SPILock.h"
|
|
#include "SafeFile.h"
|
|
|
|
namespace NicheGraphics
|
|
{
|
|
|
|
template <typename T> class FlashData
|
|
{
|
|
private:
|
|
static std::string getFilename(const char *label)
|
|
{
|
|
std::string filename;
|
|
filename += "/NicheGraphics";
|
|
filename += "/";
|
|
filename += label;
|
|
filename += ".data";
|
|
|
|
return filename;
|
|
}
|
|
|
|
static uint32_t getHash(T *data)
|
|
{
|
|
uint32_t hash = 0;
|
|
|
|
// Sum all bytes of the image buffer together
|
|
for (uint32_t i = 0; i < sizeof(T); i++)
|
|
hash ^= ((uint8_t *)data)[i] + 1;
|
|
|
|
return hash;
|
|
}
|
|
|
|
public:
|
|
static bool load(T *data, const char *label)
|
|
{
|
|
// Take firmware's SPI lock
|
|
concurrency::LockGuard guard(spiLock);
|
|
|
|
// Set false if we run into issues
|
|
bool okay = true;
|
|
|
|
// Get a filename based on the label
|
|
std::string filename = getFilename(label);
|
|
|
|
#ifdef FSCom
|
|
|
|
// Check that the file *does* actually exist
|
|
if (!FSCom.exists(filename.c_str())) {
|
|
LOG_WARN("'%s' not found. Using default values", filename.c_str());
|
|
okay = false;
|
|
return okay;
|
|
}
|
|
|
|
// Open the file
|
|
auto f = FSCom.open(filename.c_str(), FILE_O_READ);
|
|
|
|
// If opened, start reading
|
|
if (f) {
|
|
LOG_INFO("Loading NicheGraphics data '%s'", filename.c_str());
|
|
|
|
// Create an object which will received data from flash
|
|
// We read here first, so we can verify the checksum, without committing to overwriting the *data object
|
|
// Allows us to retain any defaults that might be set after we declared *data, but before loading settings,
|
|
// in case the flash values are corrupt
|
|
T flashData;
|
|
|
|
// Read the actual data
|
|
f.readBytes((char *)&flashData, sizeof(T));
|
|
|
|
// Read the hash
|
|
uint32_t savedHash = 0;
|
|
f.readBytes((char *)&savedHash, sizeof(savedHash));
|
|
|
|
// Calculate hash of the loaded data, then compare with the saved hash
|
|
// If hash looks good, copy the values to the main data object
|
|
uint32_t calculatedHash = getHash(&flashData);
|
|
if (savedHash != calculatedHash) {
|
|
LOG_WARN("'%s' is corrupt (hash mismatch). Using default values", filename.c_str());
|
|
okay = false;
|
|
} else
|
|
*data = flashData;
|
|
|
|
f.close();
|
|
} else {
|
|
LOG_ERROR("Could not open / read %s", filename.c_str());
|
|
okay = false;
|
|
}
|
|
#else
|
|
LOG_ERROR("Filesystem not implemented");
|
|
state = LoadFileState::NO_FILESYSTEM;
|
|
okay = false;
|
|
#endif
|
|
return okay;
|
|
}
|
|
|
|
// Save module's custom data (settings?) to flash. Doesn't use protobufs
|
|
// Takes the firmware's SPI lock, in case the files are stored on SD card
|
|
// Need to lock and unlock around specific FS methods, as the SafeFile class takes the lock for itself internally.
|
|
static void save(T *data, const char *label)
|
|
{
|
|
// Get a filename based on the label
|
|
std::string filename = getFilename(label);
|
|
|
|
#ifdef FSCom
|
|
spiLock->lock();
|
|
FSCom.mkdir("/NicheGraphics");
|
|
spiLock->unlock();
|
|
|
|
auto f = SafeFile(filename.c_str(), true); // "true": full atomic. Write new data to temp file, then rename.
|
|
|
|
LOG_INFO("Saving %s", filename.c_str());
|
|
|
|
// Calculate a hash of the data
|
|
uint32_t hash = getHash(data);
|
|
|
|
spiLock->lock();
|
|
f.write((uint8_t *)data, sizeof(T)); // Write the actual data
|
|
f.write((uint8_t *)&hash, sizeof(hash)); // Append the hash
|
|
spiLock->unlock();
|
|
|
|
bool writeSucceeded = f.close();
|
|
|
|
if (!writeSucceeded) {
|
|
LOG_ERROR("Can't write data!");
|
|
}
|
|
#else
|
|
LOG_ERROR("ERROR: Filesystem not implemented\n");
|
|
#endif
|
|
}
|
|
};
|
|
|
|
// Erase contents of the NicheGraphics data directory
|
|
inline void clearFlashData()
|
|
{
|
|
|
|
// Take firmware's SPI lock, in case the files are stored on SD card
|
|
concurrency::LockGuard guard(spiLock);
|
|
|
|
#ifdef FSCom
|
|
File dir = FSCom.open("/NicheGraphics"); // Open the directory
|
|
File file = dir.openNextFile(); // Attempt to open the first file in the directory
|
|
|
|
// While the directory still contains files
|
|
while (file) {
|
|
std::string path = "/NicheGraphics/";
|
|
path += file.name();
|
|
LOG_DEBUG("Erasing %s", path.c_str());
|
|
file.close();
|
|
FSCom.remove(path.c_str());
|
|
|
|
file = dir.openNextFile();
|
|
}
|
|
#else
|
|
LOG_ERROR("ERROR: Filesystem not implemented\n");
|
|
#endif
|
|
}
|
|
|
|
} // namespace NicheGraphics
|
|
|
|
#endif |