diff --git a/api/icsneocpp/event.cpp b/api/icsneocpp/event.cpp index 27eb9ba..82a4abb 100644 --- a/api/icsneocpp/event.cpp +++ b/api/icsneocpp/event.cpp @@ -113,6 +113,8 @@ static constexpr const char* ATOMIC_OPERATION_COMPLETED_NONATOMICALLY = "An idea static constexpr const char* WIVI_STACK_REFRESH_FAILED = "The Wireless neoVI stack encountered a communication error."; static constexpr const char* WIVI_UPLOAD_STACK_OVERFLOW = "The Wireless neoVI upload stack has encountered an overflow condition."; static constexpr const char* A2B_MESSAGE_INCOMPLETE_FRAME = "At least one of the frames of the A2B message does not contain samples for each channel and stream."; +static constexpr const char* COREMINI_UPLOAD_VERSION_MISMATCH = "The version of the coremini engine on the device and the script uploaded are not the same."; +static constexpr const char* DISK_NOT_CONNECTED = "The program tried to access a disk that is not connected."; // Transport Errors static constexpr const char* FAILED_TO_READ = "A read operation failed."; @@ -249,7 +251,10 @@ const char* APIEvent::DescriptionForType(Type type) { return WIVI_UPLOAD_STACK_OVERFLOW; case Type::A2BMessageIncompleteFrame: return A2B_MESSAGE_INCOMPLETE_FRAME; - + case Type::CoreminiUploadVersionMismatch: + return COREMINI_UPLOAD_VERSION_MISMATCH; + case Type::DiskNotConnected: + return DISK_NOT_CONNECTED; // Transport Errors case Type::FailedToRead: return FAILED_TO_READ; diff --git a/device/device.cpp b/device/device.cpp index 4ae1fca..76b50d2 100644 --- a/device/device.cpp +++ b/device/device.cpp @@ -445,7 +445,7 @@ int8_t Device::prepareScriptLoad() { return retVal; } -bool Device::startScript() +bool Device::startScript(Disk::MemoryType memType) { if(!isOpen()) { report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error); @@ -454,8 +454,8 @@ bool Device::startScript() std::lock_guard lg(diskLock); - uint8_t LocationSdCard = 1; //Only support starting a coremini in an SDCard - auto generic = com->sendCommand(Command::LoadCoreMini, LocationSdCard); + uint8_t location = static_cast(memType); + auto generic = com->sendCommand(Command::LoadCoreMini, location); if(!generic) { @@ -486,6 +486,68 @@ bool Device::stopScript() return true; } +bool Device::uploadCoremini(std::unique_ptr&& stream, Disk::MemoryType memType) { + + auto startAddress = getCoreminiStartAddress(memType); + if(!startAddress) { + return false; + } + + auto connected = isLogicalDiskConnected(); + + if(!connected) { + return false; // Already added an API error + } + + if(!(*connected)) { + report(APIEvent::Type::DiskNotConnected, APIEvent::Severity::Error); + return false; + } + + if(!stopScript()) { + return false; + } + + if(!stream || stream->bad()) { + report(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error); + return false; + } + + std::vector bin(std::istreambuf_iterator(*stream), {}); // Read the whole stream + + if(bin.size() < 4) { + report(APIEvent::Type::BufferInsufficient, APIEvent::Severity::Error); + return false; + } + + uint16_t scriptVersion = *(uint16_t*)(&bin[2]); // Third and fourth byte are version number stored in little endian + + auto scriptStatus = getScriptStatus(); + + if(!scriptStatus) { + return false; // Already added an API error + } + + if(scriptStatus->coreminiVersion != scriptVersion) { + // Version on device and script are not the same + report(APIEvent::Type::CoreminiUploadVersionMismatch, APIEvent::Severity::Error); + return false; + } + + auto numWritten = writeLogicalDisk(*startAddress, (uint8_t*)bin.data(), static_cast(bin.size()), std::chrono::milliseconds(2000), memType); + + if(!numWritten) { + return false; // Already added an API error + } + + if(*numWritten == 0) { + report(APIEvent::Type::FailedToWrite, APIEvent::Severity::Error); + return false; // Failed to write + } + + return true; +} + bool Device::clearScript() { if(!stopScript()) @@ -564,7 +626,8 @@ Network Device::getNetworkByNumber(Network::Type type, size_t index) const { return Network::NetID::Invalid; } -std::optional Device::readLogicalDisk(uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout) { + +std::optional Device::readLogicalDisk(uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout, Disk::MemoryType memType) { if(!into || timeout <= std::chrono::milliseconds(0)) { report(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error); return std::nullopt; @@ -579,9 +642,9 @@ std::optional Device::readLogicalDisk(uint64_t pos, uint8_t* into, uin if(diskReadDriver->getAccess() == Disk::Access::EntireCard && diskWriteDriver->getAccess() == Disk::Access::VSA) { // We have mismatched drivers, we need to add an offset to the diskReadDriver - const auto offset = Disk::FindVSAInFAT([this, &timeout](uint64_t pos, uint8_t *into, uint64_t amount) { + const auto offset = Disk::FindVSAInFAT([this, &timeout, &memType](uint64_t pos, uint8_t *into, uint64_t amount) { const auto start = std::chrono::steady_clock::now(); - auto ret = diskReadDriver->readLogicalDisk(*com, report, pos, into, amount, timeout); + auto ret = diskReadDriver->readLogicalDisk(*com, report, pos, into, amount, timeout, memType); timeout -= std::chrono::duration_cast(std::chrono::steady_clock::now() - start); return ret; }); @@ -593,10 +656,10 @@ std::optional Device::readLogicalDisk(uint64_t pos, uint8_t* into, uin // This is needed for certain read drivers which take over the communication stream const auto lifetime = suppressDisconnects(); - return diskReadDriver->readLogicalDisk(*com, report, pos, into, amount, timeout); + return diskReadDriver->readLogicalDisk(*com, report, pos, into, amount, timeout, memType); } -std::optional Device::writeLogicalDisk(uint64_t pos, const uint8_t* from, uint64_t amount, std::chrono::milliseconds timeout) { +std::optional Device::writeLogicalDisk(uint64_t pos, const uint8_t* from, uint64_t amount, std::chrono::milliseconds timeout, Disk::MemoryType memType) { if(!from || timeout <= std::chrono::milliseconds(0)) { report(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error); return std::nullopt; @@ -608,7 +671,7 @@ std::optional Device::writeLogicalDisk(uint64_t pos, const uint8_t* fr } std::lock_guard lk(diskLock); - return diskWriteDriver->writeLogicalDisk(*com, report, *diskReadDriver, pos, from, amount, timeout); + return diskWriteDriver->writeLogicalDisk(*com, report, *diskReadDriver, pos, from, amount, timeout, memType); } std::optional Device::isLogicalDiskConnected() { diff --git a/disk/diskreaddriver.cpp b/disk/diskreaddriver.cpp index be15e32..e4c6bce 100644 --- a/disk/diskreaddriver.cpp +++ b/disk/diskreaddriver.cpp @@ -5,7 +5,11 @@ using namespace icsneo; using namespace icsneo::Disk; std::optional ReadDriver::readLogicalDisk(Communication& com, device_eventhandler_t report, - uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout) { + uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout, Disk::MemoryType memType) { + + std::vector& cache = memType == Disk::MemoryType::SD ? cacheSD : cacheEEPROM; + uint64_t& cachePos = memType == Disk::MemoryType::SD ? cachePosSD : cachePosEEPROM; + if(amount == 0) return 0; @@ -57,7 +61,7 @@ std::optional ReadDriver::readLogicalDisk(Communication& com, device_e auto start = std::chrono::high_resolution_clock::now(); auto readAmount = readLogicalDiskAligned(com, report, currentBlock * idealBlockSize, - useAlignedReadBuffer ? alignedReadBuffer.data() : (into + intoOffset), idealBlockSize, timeout); + useAlignedReadBuffer ? alignedReadBuffer.data() : (into + intoOffset), idealBlockSize, timeout, memType); timeout -= std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start); if(!readAmount.has_value() || *readAmount < curAmt) { @@ -94,12 +98,19 @@ std::optional ReadDriver::readLogicalDisk(Communication& com, device_e return ret; } -void ReadDriver::invalidateCache(uint64_t pos, uint64_t amount) { +void ReadDriver::invalidateCache(uint64_t pos, uint64_t amount, MemoryType memType) { + std::vector& cache = memType == Disk::MemoryType::SD ? cacheSD : cacheEEPROM; + uint64_t cachePos = memType == Disk::MemoryType::SD ? cachePosSD : cachePosEEPROM; + if(pos <= cachePos + cache.size() && pos + amount >= cachePos) cache.clear(); } -std::optional ReadDriver::readFromCache(uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds staleAfter) { +std::optional ReadDriver::readFromCache(uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds staleAfter, MemoryType memType) { + + std::vector& cache = memType == Disk::MemoryType::SD ? cacheSD : cacheEEPROM; + uint64_t cachePos = memType == Disk::MemoryType::SD ? cachePosSD : cachePosEEPROM; + if(cache.empty()) return std::nullopt; // Nothing in the cache diff --git a/disk/diskwritedriver.cpp b/disk/diskwritedriver.cpp index e49fc56..ce8f410 100644 --- a/disk/diskwritedriver.cpp +++ b/disk/diskwritedriver.cpp @@ -5,7 +5,7 @@ using namespace icsneo; using namespace icsneo::Disk; std::optional WriteDriver::writeLogicalDisk(Communication& com, device_eventhandler_t report, ReadDriver& readDriver, - uint64_t pos, const uint8_t* from, uint64_t amount, std::chrono::milliseconds timeout) { + uint64_t pos, const uint8_t* from, uint64_t amount, std::chrono::milliseconds timeout, MemoryType memType) { if(amount == 0) return 0; @@ -51,7 +51,7 @@ std::optional WriteDriver::writeLogicalDisk(Communication& com, device const bool useAlignedWriteBuffer = (posWithinCurrentBlock != 0 || curAmt != idealBlockSize); if(useAlignedWriteBuffer) { auto read = readDriver.readLogicalDisk(com, reportFromRead, currentBlock * idealBlockSize, - alignedWriteBuffer.data(), idealBlockSize, timeout); + alignedWriteBuffer.data(), idealBlockSize, timeout, memType); timeout -= std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start); if(read != idealBlockSize) @@ -62,7 +62,7 @@ std::optional WriteDriver::writeLogicalDisk(Communication& com, device start = std::chrono::high_resolution_clock::now(); auto bytesTransferred = writeLogicalDiskAligned(com, report, currentBlock * idealBlockSize, - useAlignedWriteBuffer ? alignedWriteBuffer.data() : (from + fromOffset), idealBlockSize, timeout); + useAlignedWriteBuffer ? alignedWriteBuffer.data() : (from + fromOffset), idealBlockSize, timeout, memType); timeout -= std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start); if(!bytesTransferred.has_value() || *bytesTransferred < curAmt) { @@ -83,6 +83,6 @@ std::optional WriteDriver::writeLogicalDisk(Communication& com, device // No matter how much succeeded, to be safe, we'll invalidate anything // we may have even tried to write, since it may have succeeded without // notifying, etc. - readDriver.invalidateCache(pos, amount); + readDriver.invalidateCache(pos, amount, memType); return ret; } \ No newline at end of file diff --git a/disk/extextractordiskreaddriver.cpp b/disk/extextractordiskreaddriver.cpp index f0857a7..2a4ac2b 100644 --- a/disk/extextractordiskreaddriver.cpp +++ b/disk/extextractordiskreaddriver.cpp @@ -13,7 +13,7 @@ using namespace icsneo; using namespace icsneo::Disk; std::optional ExtExtractorDiskReadDriver::readLogicalDiskAligned(Communication& com, device_eventhandler_t report, - uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout) { + uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout, MemoryType memType) { if(amount > getBlockSizeBounds().second) return std::nullopt; @@ -28,7 +28,7 @@ std::optional ExtExtractorDiskReadDriver::readLogicalDiskAligned(Commu unsigned int attempts = 4; while (attempts-- > 0) { - ret = attemptReadLogicalDiskAligned(com, report, pos, into, amount, timeout); + ret = attemptReadLogicalDiskAligned(com, report, pos, into, amount, timeout, memType); if (ret.has_value()) break; } @@ -36,7 +36,7 @@ std::optional ExtExtractorDiskReadDriver::readLogicalDiskAligned(Commu } std::optional ExtExtractorDiskReadDriver::attemptReadLogicalDiskAligned(Communication& com, device_eventhandler_t report, - uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout) { + uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout, MemoryType) { static std::shared_ptr NeoMemorySDRead = std::make_shared(Network::NetID::NeoMemorySDRead); uint64_t sector = pos / SectorSize; diff --git a/disk/neomemorydiskdriver.cpp b/disk/neomemorydiskdriver.cpp index b7f6a86..601db17 100644 --- a/disk/neomemorydiskdriver.cpp +++ b/disk/neomemorydiskdriver.cpp @@ -1,12 +1,13 @@ #include "icsneo/disk/neomemorydiskdriver.h" #include "icsneo/communication/message/neoreadmemorysdmessage.h" #include +#include using namespace icsneo; using namespace icsneo::Disk; std::optional NeoMemoryDiskDriver::readLogicalDiskAligned(Communication& com, device_eventhandler_t report, - uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout) { + uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout, MemoryType memType) { static std::shared_ptr NeoMemorySDRead = std::make_shared(Network::NetID::NeoMemorySDRead); if(pos % SectorSize != 0) @@ -16,9 +17,11 @@ std::optional NeoMemoryDiskDriver::readLogicalDiskAligned(Communicatio return std::nullopt; const uint64_t currentSector = pos / SectorSize; - auto msg = com.waitForMessageSync([¤tSector, &com] { + const uint8_t memLocation = (uint8_t)memType; + + auto msg = com.waitForMessageSync([¤tSector, &memLocation, &com] { return com.sendCommand(Command::NeoReadMemory, { - MemoryTypeSD, + memLocation, uint8_t(currentSector & 0xFF), uint8_t((currentSector >> 8) & 0xFF), uint8_t((currentSector >> 16) & 0xFF), @@ -44,7 +47,7 @@ std::optional NeoMemoryDiskDriver::readLogicalDiskAligned(Communicatio } std::optional NeoMemoryDiskDriver::writeLogicalDiskAligned(Communication& com, device_eventhandler_t report, - uint64_t pos, const uint8_t* from, uint64_t amount, std::chrono::milliseconds timeout) { + uint64_t pos, const uint8_t* from, uint64_t amount, std::chrono::milliseconds timeout, MemoryType memType) { static std::shared_ptr NeoMemoryDone = std::make_shared(Network::NetID::NeoMemoryWriteDone); @@ -55,9 +58,11 @@ std::optional NeoMemoryDiskDriver::writeLogicalDiskAligned(Communicati return std::nullopt; const uint64_t currentSector = pos / SectorSize; - auto msg = com.waitForMessageSync([¤tSector, &com, from, amount] { + const uint8_t memLocation = (uint8_t)memType; + + auto msg = com.waitForMessageSync([¤tSector, &memLocation, &com, from, amount] { std::vector command = { - MemoryTypeSD, + memLocation, uint8_t(currentSector & 0xFF), uint8_t((currentSector >> 8) & 0xFF), uint8_t((currentSector >> 16) & 0xFF), diff --git a/disk/nulldiskdriver.cpp b/disk/nulldiskdriver.cpp index eccdd87..c78abb1 100644 --- a/disk/nulldiskdriver.cpp +++ b/disk/nulldiskdriver.cpp @@ -4,25 +4,25 @@ using namespace icsneo; using namespace icsneo::Disk; std::optional NullDriver::readLogicalDisk(Communication&, device_eventhandler_t report, - uint64_t, uint8_t*, uint64_t, std::chrono::milliseconds) { + uint64_t, uint8_t*, uint64_t, std::chrono::milliseconds, MemoryType) { report(APIEvent::Type::DiskNotSupported, APIEvent::Severity::Error); return std::nullopt; } std::optional NullDriver::readLogicalDiskAligned(Communication&, device_eventhandler_t report, - uint64_t, uint8_t*, uint64_t, std::chrono::milliseconds) { + uint64_t, uint8_t*, uint64_t, std::chrono::milliseconds, MemoryType) { report(APIEvent::Type::DiskNotSupported, APIEvent::Severity::Error); return std::nullopt; } std::optional NullDriver::writeLogicalDisk(Communication&, device_eventhandler_t report, ReadDriver&, - uint64_t, const uint8_t*, uint64_t, std::chrono::milliseconds) { + uint64_t, const uint8_t*, uint64_t, std::chrono::milliseconds, MemoryType) { report(APIEvent::Type::DiskNotSupported, APIEvent::Severity::Error); return std::nullopt; } std::optional NullDriver::writeLogicalDiskAligned(Communication&, device_eventhandler_t report, - uint64_t, const uint8_t*, uint64_t, std::chrono::milliseconds) { + uint64_t, const uint8_t*, uint64_t, std::chrono::milliseconds, MemoryType) { report(APIEvent::Type::DiskNotSupported, APIEvent::Severity::Error); return std::nullopt; } \ No newline at end of file diff --git a/disk/plasiondiskreaddriver.cpp b/disk/plasiondiskreaddriver.cpp index 2018b21..466c7dd 100644 --- a/disk/plasiondiskreaddriver.cpp +++ b/disk/plasiondiskreaddriver.cpp @@ -7,7 +7,7 @@ using namespace icsneo; using namespace icsneo::Disk; std::optional PlasionDiskReadDriver::readLogicalDiskAligned(Communication& com, device_eventhandler_t report, - uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout) { + uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout, MemoryType) { static std::shared_ptr NeoMemorySDRead = std::make_shared(Network::NetID::NeoMemorySDRead); if(amount > getBlockSizeBounds().second) diff --git a/include/icsneo/api/event.h b/include/icsneo/api/event.h index 85767eb..f8918ca 100644 --- a/include/icsneo/api/event.h +++ b/include/icsneo/api/event.h @@ -91,6 +91,8 @@ public: WiVIUploadStackOverflow = 0x2037, I2CMessageExceedsMaxLength = 0x2038, A2BMessageIncompleteFrame = 0x2039, + CoreminiUploadVersionMismatch = 0x2040, + DiskNotConnected = 0x2041, // Transport Events FailedToRead = 0x3000, diff --git a/include/icsneo/device/device.h b/include/icsneo/device/device.h index 7ad603e..b7c85bc 100644 --- a/include/icsneo/device/device.h +++ b/include/icsneo/device/device.h @@ -55,6 +55,8 @@ namespace icsneo { class DeviceExtension; +typedef uint64_t MemoryAddress; + class Device { public: virtual ~Device(); @@ -135,10 +137,34 @@ public: NoScript, }; + + int8_t prepareScriptLoad(); - bool startScript(); + bool startScript(Disk::MemoryType memType = Disk::MemoryType::SD); bool stopScript(); bool clearScript(); + bool uploadCoremini(std::unique_ptr&& stream, Disk::MemoryType memType = Disk::MemoryType::SD); + + virtual std::optional getCoreminiStartAddressFlash() const { + return std::nullopt; + } + + virtual std::optional getCoreminiStartAddressSD() const { + return std::nullopt; + } + + std::optional getCoreminiStartAddress(Disk::MemoryType memType) const { + switch(memType) { + case Disk::MemoryType::Flash: + return getCoreminiStartAddressFlash(); + case Disk::MemoryType::SD: + return getCoreminiStartAddressSD(); + default: + break; + } + return std::nullopt; + } + // Message polling related functions bool enableMessagePolling(); @@ -173,6 +199,8 @@ public: virtual size_t getNetworkCountByType(Network::Type) const; virtual Network getNetworkByNumber(Network::Type, size_t) const; + + /** * Read from the logical disk in this device, starting from byte `pos` * and reading up to `amount` bytes. @@ -188,7 +216,7 @@ public: * set in icsneo::GetLastError(). */ std::optional readLogicalDisk(uint64_t pos, uint8_t* into, uint64_t amount, - std::chrono::milliseconds timeout = Disk::DefaultTimeout); + std::chrono::milliseconds timeout = Disk::DefaultTimeout, Disk::MemoryType memType = Disk::MemoryType::SD); /** * Write to the logical disk in this device, starting from byte `pos` @@ -205,7 +233,7 @@ public: * set in icsneo::GetLastError(). */ std::optional writeLogicalDisk(uint64_t pos, const uint8_t* from, uint64_t amount, - std::chrono::milliseconds timeout = Disk::DefaultTimeout); + std::chrono::milliseconds timeout = Disk::DefaultTimeout, Disk::MemoryType memType = Disk::MemoryType::SD); /** * Check if the logical disk is connected. This means the disk is inserted, diff --git a/include/icsneo/device/tree/etherbadge/etherbadge.h b/include/icsneo/device/tree/etherbadge/etherbadge.h index 9e8ed96..167d6f1 100644 --- a/include/icsneo/device/tree/etherbadge/etherbadge.h +++ b/include/icsneo/device/tree/etherbadge/etherbadge.h @@ -45,6 +45,15 @@ protected: void setupSupportedTXNetworks(std::vector& txNetworks) override { setupSupportedRXNetworks(txNetworks); } bool requiresVehiclePower() const override { return false; } + + std::optional getCoreminiStartAddressFlash() const override { + return 2048 * 512; + } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } + }; } diff --git a/include/icsneo/device/tree/neoobd2pro/neoobd2pro.h b/include/icsneo/device/tree/neoobd2pro/neoobd2pro.h index 15712d3..549fc3b 100644 --- a/include/icsneo/device/tree/neoobd2pro/neoobd2pro.h +++ b/include/icsneo/device/tree/neoobd2pro/neoobd2pro.h @@ -36,6 +36,14 @@ private: void setupSupportedTXNetworks(std::vector& txNetworks) override { setupSupportedRXNetworks(txNetworks); } bool requiresVehiclePower() const override { return false; } + + std::optional getCoreminiStartAddressFlash() const override { + return 2048 * 512; + } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } }; } diff --git a/include/icsneo/device/tree/neoobd2sim/neoobd2sim.h b/include/icsneo/device/tree/neoobd2sim/neoobd2sim.h index ed13ffb..ac8f48c 100644 --- a/include/icsneo/device/tree/neoobd2sim/neoobd2sim.h +++ b/include/icsneo/device/tree/neoobd2sim/neoobd2sim.h @@ -36,6 +36,14 @@ private: void setupSupportedTXNetworks(std::vector& txNetworks) override { setupSupportedRXNetworks(txNetworks); } bool requiresVehiclePower() const override { return false; } + + std::optional getCoreminiStartAddressFlash() const override { + return 2048 * 512; + } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } }; } diff --git a/include/icsneo/device/tree/neovifire/neovifire.h b/include/icsneo/device/tree/neovifire/neovifire.h index ff7a17c..37fed45 100644 --- a/include/icsneo/device/tree/neovifire/neovifire.h +++ b/include/icsneo/device/tree/neovifire/neovifire.h @@ -69,6 +69,14 @@ private: // The supported TX networks are the same as the supported RX networks for this device void setupSupportedTXNetworks(std::vector& txNetworks) override { setupSupportedRXNetworks(txNetworks); } + + std::optional getCoreminiStartAddressFlash() const override { + return 4 * 512; + } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } }; } diff --git a/include/icsneo/device/tree/neovifire2/neovifire2.h b/include/icsneo/device/tree/neovifire2/neovifire2.h index c799eea..0d9d258 100644 --- a/include/icsneo/device/tree/neovifire2/neovifire2.h +++ b/include/icsneo/device/tree/neovifire2/neovifire2.h @@ -129,6 +129,14 @@ protected: ethActivationStatus = status->ethernetActivationLineEnabled; usbHostPowerStatus = status->usbHostPowerEnabled; } + + std::optional getCoreminiStartAddressFlash() const override { + return 4608 * 512; + } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } }; } diff --git a/include/icsneo/device/tree/neovifire3/neovifire3.h b/include/icsneo/device/tree/neovifire3/neovifire3.h index 58704cc..433a8ce 100644 --- a/include/icsneo/device/tree/neovifire3/neovifire3.h +++ b/include/icsneo/device/tree/neovifire3/neovifire3.h @@ -74,6 +74,14 @@ protected: void setupSupportedTXNetworks(std::vector& txNetworks) override { setupSupportedRXNetworks(txNetworks); } bool supportsWiVI() const override { return true; } + + std::optional getCoreminiStartAddressFlash() const override { + return 33*1024*1024; + } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } }; } diff --git a/include/icsneo/device/tree/neovifire3flexray/neovifire3flexray.h b/include/icsneo/device/tree/neovifire3flexray/neovifire3flexray.h index b18851a..e8eecb7 100644 --- a/include/icsneo/device/tree/neovifire3flexray/neovifire3flexray.h +++ b/include/icsneo/device/tree/neovifire3flexray/neovifire3flexray.h @@ -76,6 +76,14 @@ protected: void setupSupportedTXNetworks(std::vector& txNetworks) override { setupSupportedRXNetworks(txNetworks); } bool supportsWiVI() const override { return true; } + + std::optional getCoreminiStartAddressFlash() const override { + return 512*4; + } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } }; } diff --git a/include/icsneo/device/tree/neovired2/neovired2.h b/include/icsneo/device/tree/neovired2/neovired2.h index 1c92109..51fe687 100644 --- a/include/icsneo/device/tree/neovired2/neovired2.h +++ b/include/icsneo/device/tree/neovired2/neovired2.h @@ -59,6 +59,14 @@ protected: void setupSupportedTXNetworks(std::vector& txNetworks) override { setupSupportedRXNetworks(txNetworks); } bool supportsWiVI() const override { return true; } + + std::optional getCoreminiStartAddressFlash() const override { + return 33*1024*1024; + } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } }; } diff --git a/include/icsneo/device/tree/plasion/neoviion.h b/include/icsneo/device/tree/plasion/neoviion.h index 47a2860..b3896f3 100644 --- a/include/icsneo/device/tree/plasion/neoviion.h +++ b/include/icsneo/device/tree/plasion/neoviion.h @@ -35,6 +35,10 @@ private: 1 // 2 ); } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } }; } diff --git a/include/icsneo/device/tree/plasion/neoviplasma.h b/include/icsneo/device/tree/plasion/neoviplasma.h index 1b40c1a..3f8f629 100644 --- a/include/icsneo/device/tree/plasion/neoviplasma.h +++ b/include/icsneo/device/tree/plasion/neoviplasma.h @@ -33,6 +33,10 @@ private: 1 // 3 ); } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } }; } diff --git a/include/icsneo/device/tree/rada2b/rada2b.h b/include/icsneo/device/tree/rada2b/rada2b.h index 1777c23..862e0f3 100644 --- a/include/icsneo/device/tree/rada2b/rada2b.h +++ b/include/icsneo/device/tree/rada2b/rada2b.h @@ -7,6 +7,7 @@ #include "icsneo/device/devicetype.h" #include "icsneo/communication/packetizer.h" #include "icsneo/communication/decoder.h" +#include "icsneo/disk/neomemorydiskdriver.h" #include "icsneo/device/tree/rada2b/rada2bsettings.h" namespace icsneo { @@ -40,7 +41,7 @@ public: protected: RADA2B(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) { - initialize(makeDriver); + initialize(makeDriver); } void setupPacketizer(Packetizer& packetizer) override { @@ -66,6 +67,14 @@ protected: // The supported TX networks are the same as the supported RX networks for this device void setupSupportedTXNetworks(std::vector& txNetworks) override { setupSupportedRXNetworks(txNetworks); } + + std::optional getCoreminiStartAddressFlash() const override { + return 15*1024*1024; + } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } }; } diff --git a/include/icsneo/device/tree/radepsilon/radepsilon.h b/include/icsneo/device/tree/radepsilon/radepsilon.h index 9b35b6e..8736785 100644 --- a/include/icsneo/device/tree/radepsilon/radepsilon.h +++ b/include/icsneo/device/tree/radepsilon/radepsilon.h @@ -41,6 +41,14 @@ protected: // The supported TX networks are the same as the supported RX networks for this device void setupSupportedTXNetworks(std::vector& txNetworks) override { setupSupportedRXNetworks(txNetworks); } + + std::optional getCoreminiStartAddressFlash() const override { + return 14*1024*1024; + } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } }; } diff --git a/include/icsneo/device/tree/radgalaxy/radgalaxy.h b/include/icsneo/device/tree/radgalaxy/radgalaxy.h index fefbdef..450c86e 100644 --- a/include/icsneo/device/tree/radgalaxy/radgalaxy.h +++ b/include/icsneo/device/tree/radgalaxy/radgalaxy.h @@ -89,6 +89,14 @@ protected: const radgalaxy_status_t* status = reinterpret_cast(message->data.data()); ethActivationStatus = status->ethernetActivationLineEnabled; } + + std::optional getCoreminiStartAddressFlash() const override { + return 512*4; + } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } }; } diff --git a/include/icsneo/device/tree/radgigastar/radgigastar.h b/include/icsneo/device/tree/radgigastar/radgigastar.h index 6f6f747..43c31db 100644 --- a/include/icsneo/device/tree/radgigastar/radgigastar.h +++ b/include/icsneo/device/tree/radgigastar/radgigastar.h @@ -98,6 +98,14 @@ protected: const radgigastar_status_t* status = reinterpret_cast(message->data.data()); ethActivationStatus = status->ethernetActivationLineEnabled; } + + std::optional getCoreminiStartAddressFlash() const override { + return 512*4; + } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } }; } diff --git a/include/icsneo/device/tree/radjupiter/radjupiter.h b/include/icsneo/device/tree/radjupiter/radjupiter.h index 84b64ff..c5649e2 100644 --- a/include/icsneo/device/tree/radjupiter/radjupiter.h +++ b/include/icsneo/device/tree/radjupiter/radjupiter.h @@ -49,6 +49,14 @@ protected: void setupSupportedTXNetworks(std::vector& txNetworks) override { setupSupportedRXNetworks(txNetworks); } bool requiresVehiclePower() const override { return false; } + + std::optional getCoreminiStartAddressFlash() const override { + return 512*2048; + } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } }; } diff --git a/include/icsneo/device/tree/radmars/radmars.h b/include/icsneo/device/tree/radmars/radmars.h index 67eaa32..42993e3 100644 --- a/include/icsneo/device/tree/radmars/radmars.h +++ b/include/icsneo/device/tree/radmars/radmars.h @@ -86,6 +86,14 @@ protected: const radmars_status_t* status = reinterpret_cast(message->data.data()); ethActivationStatus = status->ethernetActivationLineEnabled; } + + std::optional getCoreminiStartAddressFlash() const override { + return 512*4; + } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } }; } diff --git a/include/icsneo/device/tree/radmoon2/radmoon2.h b/include/icsneo/device/tree/radmoon2/radmoon2.h index 94f70c8..a4312c9 100644 --- a/include/icsneo/device/tree/radmoon2/radmoon2.h +++ b/include/icsneo/device/tree/radmoon2/radmoon2.h @@ -81,6 +81,14 @@ protected: } bool requiresVehiclePower() const override { return false; } + + std::optional getCoreminiStartAddressFlash() const override { + return 512*4; + } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } }; } diff --git a/include/icsneo/device/tree/radmoonduo/radmoonduo.h b/include/icsneo/device/tree/radmoonduo/radmoonduo.h index 3466cb3..50407c3 100644 --- a/include/icsneo/device/tree/radmoonduo/radmoonduo.h +++ b/include/icsneo/device/tree/radmoonduo/radmoonduo.h @@ -45,6 +45,13 @@ protected: bool requiresVehiclePower() const override { return false; } + std::optional getCoreminiStartAddressFlash() const override { + return 512*2048; + } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } }; } diff --git a/include/icsneo/device/tree/radpluto/radpluto.h b/include/icsneo/device/tree/radpluto/radpluto.h index 038cb2f..f8b9b01 100644 --- a/include/icsneo/device/tree/radpluto/radpluto.h +++ b/include/icsneo/device/tree/radpluto/radpluto.h @@ -54,6 +54,14 @@ protected: void setupSupportedTXNetworks(std::vector& txNetworks) override { setupSupportedRXNetworks(txNetworks); } bool requiresVehiclePower() const override { return false; } + + std::optional getCoreminiStartAddressFlash() const override { + return 512*2048; + } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } }; } diff --git a/include/icsneo/device/tree/radstar2/radstar2.h b/include/icsneo/device/tree/radstar2/radstar2.h index 173c58d..346611b 100644 --- a/include/icsneo/device/tree/radstar2/radstar2.h +++ b/include/icsneo/device/tree/radstar2/radstar2.h @@ -57,6 +57,14 @@ protected: // The supported TX networks are the same as the supported RX networks for this device void setupSupportedTXNetworks(std::vector& txNetworks) override { setupSupportedRXNetworks(txNetworks); } + + std::optional getCoreminiStartAddressFlash() const override { + return 512*4; + } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } }; } diff --git a/include/icsneo/device/tree/radsupermoon/radsupermoon.h b/include/icsneo/device/tree/radsupermoon/radsupermoon.h index d905f42..be92de7 100644 --- a/include/icsneo/device/tree/radsupermoon/radsupermoon.h +++ b/include/icsneo/device/tree/radsupermoon/radsupermoon.h @@ -79,6 +79,14 @@ protected: void setupSupportedTXNetworks(std::vector& txNetworks) override { setupSupportedRXNetworks(txNetworks); } bool requiresVehiclePower() const override { return false; } + + std::optional getCoreminiStartAddressFlash() const override { + return 512*4; + } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } }; } diff --git a/include/icsneo/device/tree/valuecan3/valuecan3.h b/include/icsneo/device/tree/valuecan3/valuecan3.h index 6d2bf74..e78e383 100644 --- a/include/icsneo/device/tree/valuecan3/valuecan3.h +++ b/include/icsneo/device/tree/valuecan3/valuecan3.h @@ -36,6 +36,14 @@ private: void setupSupportedTXNetworks(std::vector& txNetworks) override { setupSupportedRXNetworks(txNetworks); } bool requiresVehiclePower() const override { return false; } + + std::optional getCoreminiStartAddressFlash() const override { + return 512*2048; + } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } }; } diff --git a/include/icsneo/device/tree/valuecan4/valuecan4.h b/include/icsneo/device/tree/valuecan4/valuecan4.h index 2d19a45..fd4517b 100644 --- a/include/icsneo/device/tree/valuecan4/valuecan4.h +++ b/include/icsneo/device/tree/valuecan4/valuecan4.h @@ -21,6 +21,14 @@ protected: } bool requiresVehiclePower() const override { return false; } + + std::optional getCoreminiStartAddressFlash() const override { + return 512*2048; + } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } }; } diff --git a/include/icsneo/device/tree/vividcan/vividcan.h b/include/icsneo/device/tree/vividcan/vividcan.h index 03db1fb..7d1e50a 100644 --- a/include/icsneo/device/tree/vividcan/vividcan.h +++ b/include/icsneo/device/tree/vividcan/vividcan.h @@ -33,6 +33,14 @@ protected: } bool requiresVehiclePower() const override { return false; } + + std::optional getCoreminiStartAddressFlash() const override { + return 512*128; + } + + std::optional getCoreminiStartAddressSD() const override { + return 0; + } }; } diff --git a/include/icsneo/disk/diskdriver.h b/include/icsneo/disk/diskdriver.h index daa76ac..bc437fc 100644 --- a/include/icsneo/disk/diskdriver.h +++ b/include/icsneo/disk/diskdriver.h @@ -19,6 +19,12 @@ enum class Access { VSA }; +enum class MemoryType : uint8_t +{ + Flash = 0, + SD = 1 +}; + /** * Interface for drivers which work with block data on devices */ diff --git a/include/icsneo/disk/diskreaddriver.h b/include/icsneo/disk/diskreaddriver.h index c14d2f2..80111f5 100644 --- a/include/icsneo/disk/diskreaddriver.h +++ b/include/icsneo/disk/diskreaddriver.h @@ -20,10 +20,10 @@ namespace Disk { class ReadDriver : public virtual Driver { public: virtual std::optional readLogicalDisk(Communication& com, device_eventhandler_t report, - uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout = DefaultTimeout); + uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout = DefaultTimeout, MemoryType memType = MemoryType::SD); void invalidateCache(uint64_t pos = 0, - uint64_t amount = std::numeric_limits::max() /* large value, but avoid overflow */); + uint64_t amount = std::numeric_limits::max() /* large value, but avoid overflow */, MemoryType memType = MemoryType::SD); protected: /** @@ -33,16 +33,19 @@ protected: * within the block size bounds provided by the driver. */ virtual std::optional readLogicalDiskAligned(Communication& com, device_eventhandler_t report, - uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout) = 0; + uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout, MemoryType memType = MemoryType::SD) = 0; private: - std::vector cache; - uint64_t cachePos = 0; + std::vector cacheSD; + std::vector cacheEEPROM; + + uint64_t cachePosSD = 0; + uint64_t cachePosEEPROM = 0; std::chrono::time_point cachedAt; static constexpr const std::chrono::milliseconds CacheTime = std::chrono::milliseconds(1000); - std::optional readFromCache(uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds staleAfter = CacheTime); + std::optional readFromCache(uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds staleAfter = CacheTime, MemoryType memType = MemoryType::SD); }; } // namespace Disk diff --git a/include/icsneo/disk/diskwritedriver.h b/include/icsneo/disk/diskwritedriver.h index 93e6d47..18caa56 100644 --- a/include/icsneo/disk/diskwritedriver.h +++ b/include/icsneo/disk/diskwritedriver.h @@ -20,7 +20,7 @@ namespace Disk { class WriteDriver : public virtual Driver { public: virtual std::optional writeLogicalDisk(Communication& com, device_eventhandler_t report, ReadDriver& readDriver, - uint64_t pos, const uint8_t* from, uint64_t amount, std::chrono::milliseconds timeout = DefaultTimeout); + uint64_t pos, const uint8_t* from, uint64_t amount, std::chrono::milliseconds timeout = DefaultTimeout, MemoryType memType = MemoryType::SD); protected: /** @@ -30,7 +30,7 @@ protected: * within the block size bounds provided by the driver. */ virtual std::optional writeLogicalDiskAligned(Communication& com, device_eventhandler_t report, - uint64_t pos, const uint8_t* from, uint64_t amount, std::chrono::milliseconds timeout) = 0; + uint64_t pos, const uint8_t* from, uint64_t amount, std::chrono::milliseconds timeout, MemoryType memType = MemoryType::SD) = 0; }; } // namespace Disk diff --git a/include/icsneo/disk/extextractordiskreaddriver.h b/include/icsneo/disk/extextractordiskreaddriver.h index c218b1e..be2827b 100644 --- a/include/icsneo/disk/extextractordiskreaddriver.h +++ b/include/icsneo/disk/extextractordiskreaddriver.h @@ -29,10 +29,10 @@ private: Access getPossibleAccess() const override { return Access::EntireCard; } std::optional readLogicalDiskAligned(Communication& com, device_eventhandler_t report, - uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout) override; + uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout, MemoryType memType = MemoryType::SD) override; std::optional attemptReadLogicalDiskAligned(Communication& com, device_eventhandler_t report, - uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout); + uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout, MemoryType memType = MemoryType::SD); }; } // namespace Disk diff --git a/include/icsneo/disk/neomemorydiskdriver.h b/include/icsneo/disk/neomemorydiskdriver.h index 4fa7bfc..2636efd 100644 --- a/include/icsneo/disk/neomemorydiskdriver.h +++ b/include/icsneo/disk/neomemorydiskdriver.h @@ -31,10 +31,10 @@ private: Access getPossibleAccess() const override { return Access::VSA; } std::optional readLogicalDiskAligned(Communication& com, device_eventhandler_t report, - uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout) override; + uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout, MemoryType memType = MemoryType::SD) override; std::optional writeLogicalDiskAligned(Communication& com, device_eventhandler_t report, - uint64_t pos, const uint8_t* from, uint64_t amount, std::chrono::milliseconds timeout) override; + uint64_t pos, const uint8_t* from, uint64_t amount, std::chrono::milliseconds timeout, MemoryType memType = MemoryType::SD) override; }; } // namespace Disk diff --git a/include/icsneo/disk/nulldiskdriver.h b/include/icsneo/disk/nulldiskdriver.h index 1d40ca6..a999e79 100644 --- a/include/icsneo/disk/nulldiskdriver.h +++ b/include/icsneo/disk/nulldiskdriver.h @@ -19,9 +19,9 @@ namespace Disk { class NullDriver : public ReadDriver, public WriteDriver { public: std::optional readLogicalDisk(Communication& com, device_eventhandler_t report, - uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout = DefaultTimeout) override; + uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout = DefaultTimeout, MemoryType memType = MemoryType::SD) override; std::optional writeLogicalDisk(Communication& com, device_eventhandler_t report, ReadDriver& readDriver, - uint64_t pos, const uint8_t* from, uint64_t amount, std::chrono::milliseconds timeout = DefaultTimeout) override; + uint64_t pos, const uint8_t* from, uint64_t amount, std::chrono::milliseconds timeout = DefaultTimeout, MemoryType memType = MemoryType::SD) override; std::pair getBlockSizeBounds() const override { static_assert(SectorSize <= std::numeric_limits::max(), "Incorrect sector size"); static_assert(SectorSize >= std::numeric_limits::min(), "Incorrect sector size"); @@ -32,9 +32,9 @@ private: Access getPossibleAccess() const override { return Access::None; } std::optional readLogicalDiskAligned(Communication& com, device_eventhandler_t report, - uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout) override; + uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout, MemoryType memType = MemoryType::SD) override; std::optional writeLogicalDiskAligned(Communication& com, device_eventhandler_t report, - uint64_t pos, const uint8_t* from, uint64_t amount, std::chrono::milliseconds timeout) override; + uint64_t pos, const uint8_t* from, uint64_t amount, std::chrono::milliseconds timeout, MemoryType memType = MemoryType::SD) override; }; } // namespace Disk diff --git a/include/icsneo/disk/plasiondiskreaddriver.h b/include/icsneo/disk/plasiondiskreaddriver.h index c97d0c5..7639e0d 100644 --- a/include/icsneo/disk/plasiondiskreaddriver.h +++ b/include/icsneo/disk/plasiondiskreaddriver.h @@ -28,7 +28,7 @@ private: Access getPossibleAccess() const override { return Access::EntireCard; } std::optional readLogicalDiskAligned(Communication& com, device_eventhandler_t report, - uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout) override; + uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout, MemoryType memType = MemoryType::SD) override; }; } // namespace Disk diff --git a/test/diskdrivertest.h b/test/diskdrivertest.h index 946b208..87441ad 100644 --- a/test/diskdrivertest.h +++ b/test/diskdrivertest.h @@ -18,7 +18,7 @@ public: std::pair getBlockSizeBounds() const override { return { 8, 256 }; } std::optional readLogicalDiskAligned(Communication&, device_eventhandler_t, - uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds) override { + uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds, Disk::MemoryType) override { readCalls++; EXPECT_EQ(pos % getBlockSizeBounds().first, 0); // Ensure the alignment rules are respected @@ -40,7 +40,7 @@ public: } std::optional writeLogicalDiskAligned(Communication&, device_eventhandler_t report, uint64_t pos, - const uint8_t* from, uint64_t amount, std::chrono::milliseconds) override { + const uint8_t* from, uint64_t amount, std::chrono::milliseconds, Disk::MemoryType) override { writeCalls++; EXPECT_EQ(pos % getBlockSizeBounds().first, 0); // Ensure the alignment rules are respected