Files
MeshCore/src/helpers/HostKissSettings.cpp
T

83 lines
3.2 KiB
C++

#include "HostKissSettings.h"
#if MESH_ENABLE_HOST_KISS
#include "CheckedSettingsFile.h"
#include "FilePresence.h"
#include "PersistentStoreFormat.h"
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
#include "AtomicFileWriter.h"
#else
#include "ContactFileTransaction.h"
#endif
namespace mesh { namespace hostkiss {
namespace {
constexpr char Path[] = "/host_kiss";
constexpr size_t ImageSize = 12;
void encode(uint8_t (&image)[ImageSize], const Selection& value) {
memset(image, 0, sizeof(image));
memcpy(image, "HKS1", 4);
image[4] = value.enabled ? 1 : 0;
image[5] = uint8_t(value.transport);
storage::writeLE32(image + 8, storage::updateCRC32(0xffffffff, image, 8));
}
bool valid(const uint8_t (&image)[ImageSize]) {
return memcmp(image, "HKS1", 4) == 0 && image[4] <= 1 && image[5] <= 1
&& image[6] == 0 && image[7] == 0
&& storage::readLE32(image + 8) == storage::updateCRC32(0xffffffff, image, 8);
}
}
bool Settings::begin(FILESYSTEM* fs) {
fs_ = fs;
healthy_ = false;
selection_ = {};
if (!fs_) return false;
#if defined(ESP32_PLATFORM) || defined(RP2040_PLATFORM) || defined(ESP32)
if (!ContactFileTransaction::recover(fs_, Path, filePresence<FILESYSTEM>)) return false;
#endif
bool present = false;
if (!filePresence(fs_, Path, present)) return false;
if (!present) { healthy_ = true; return true; }
uint8_t image[ImageSize];
const auto result = storage::readFixedSettingsFileResult(fs_, Path, image, sizeof(image));
if (result == storage::FixedSettingsRead::Unreadable) return false;
healthy_ = true; // A complete malformed record may be explicitly replaced.
if (result != storage::FixedSettingsRead::Complete || !valid(image)) return false;
selection_.enabled = image[4] != 0;
selection_.transport = Transport(image[5]);
return true;
}
bool Settings::save(const Selection& selection) {
if (!healthy_ || !fs_ || uint8_t(selection.transport) > 1) return false;
uint8_t image[ImageSize];
encode(image, selection);
#if defined(NRF52_PLATFORM)
const auto outcome = storage::writeCheckedSettingsFile(fs_, Path, image, sizeof(image));
if (outcome == AtomicFileWriter::Outcome::Indeterminate) healthy_ = false;
if (outcome != AtomicFileWriter::Outcome::Committed) return false;
#elif defined(STM32_PLATFORM)
AtomicFileWriter writer(fs_, Path);
const bool wrote = writer && writer.write(image, sizeof(image)) == sizeof(image);
const bool saved = writer.commit(wrote);
if (writer.outcome() == AtomicFileWriter::Outcome::Indeterminate) healthy_ = false;
if (!saved) return false;
#else
ContactFileTransaction writer(fs_, Path, filePresence<FILESYSTEM>);
if (!writer || writer.write(image, sizeof(image)) != sizeof(image)) {
if (writer.outcome() == ContactFileTransaction::Outcome::Indeterminate) healthy_ = false;
return false;
}
writer.commit();
if (writer.outcome() == ContactFileTransaction::Outcome::NotCommitted) return false;
#endif
#if !defined(NRF52_PLATFORM)
uint8_t verified[ImageSize];
healthy_ = storage::readFixedSettingsFile(fs_, Path, verified, sizeof(verified))
&& memcmp(image, verified, sizeof(image)) == 0;
if (!healthy_) return false;
#endif
selection_ = selection;
return true;
}
}} // namespace mesh::hostkiss
#endif