From f8bfb243faeb5c34694369a1a0257521cd8d89df Mon Sep 17 00:00:00 2001 From: Paul Hollinsky Date: Tue, 16 Nov 2021 00:35:32 -0500 Subject: [PATCH] Disk: Implement NeoMemoryDiskReadDriver --- CMakeLists.txt | 1 + communication/decoder.cpp | 13 ++++++ communication/encoder.cpp | 1 + disk/neomemorydiskreaddriver.cpp | 40 +++++++++++++++++++ disk/nulldiskreaddriver.cpp | 12 +++--- include/icsneo/communication/command.h | 1 + .../message/neoreadmemorysdmessage.h | 20 ++++++++++ include/icsneo/communication/network.h | 7 ++-- include/icsneo/disk/neomemorydiskreaddriver.h | 35 ++++++++++++++++ include/icsneo/disk/nulldiskreaddriver.h | 7 +++- 10 files changed, 127 insertions(+), 10 deletions(-) create mode 100644 disk/neomemorydiskreaddriver.cpp create mode 100644 include/icsneo/communication/message/neoreadmemorysdmessage.h create mode 100644 include/icsneo/disk/neomemorydiskreaddriver.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a145f4..e2b305e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -150,6 +150,7 @@ set(SRC_FILES device/device.cpp disk/diskreaddriver.cpp disk/nulldiskreaddriver.cpp + disk/neomemorydiskreaddriver.cpp ${PLATFORM_SRC} ) diff --git a/communication/decoder.cpp b/communication/decoder.cpp index 039e4a1..5779eab 100644 --- a/communication/decoder.cpp +++ b/communication/decoder.cpp @@ -4,6 +4,7 @@ #include "icsneo/communication/message/resetstatusmessage.h" #include "icsneo/communication/message/readsettingsmessage.h" #include "icsneo/communication/message/canerrorcountmessage.h" +#include "icsneo/communication/message/neoreadmemorysdmessage.h" #include "icsneo/communication/message/flexray/control/flexraycontrolmessage.h" #include "icsneo/communication/command.h" #include "icsneo/device/device.h" @@ -179,6 +180,18 @@ bool Decoder::decode(std::shared_ptr& result, const std::shared_ptr(packet->network, packet->data); return true; } + case Network::NetID::NeoMemorySDRead: { + if(packet->data.size() != 512 + sizeof(uint32_t)) { + report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error); + return false; // Should get enough data for a start address and sector + } + + const auto msg = std::make_shared(); + result = msg; + msg->startAddress = *reinterpret_cast(packet->data.data()); + msg->data.insert(msg->data.end(), packet->data.begin() + 4, packet->data.end()); + return true; + } case Network::NetID::FlexRayControl: { auto frResult = std::make_shared(*packet); if(!frResult->decoded) { diff --git a/communication/encoder.cpp b/communication/encoder.cpp index 9bf60e3..986e71c 100644 --- a/communication/encoder.cpp +++ b/communication/encoder.cpp @@ -197,6 +197,7 @@ bool Encoder::encode(const Packetizer& packetizer, std::vector& result, case Command::EnableNetworkCommunicationEx: case Command::GetMainVersion: case Command::GetSecondaryVersions: + case Command::NeoReadMemory: // There is a firmware handling idiosyncrasy with these commands // They must be encoded in the short format m51msg->forceShortFormat = true; diff --git a/disk/neomemorydiskreaddriver.cpp b/disk/neomemorydiskreaddriver.cpp new file mode 100644 index 0000000..ab41e43 --- /dev/null +++ b/disk/neomemorydiskreaddriver.cpp @@ -0,0 +1,40 @@ +#include "icsneo/disk/neomemorydiskreaddriver.h" +#include "icsneo/communication/message/neoreadmemorysdmessage.h" +#include + +using namespace icsneo; + +optional NeoMemoryDiskReadDriver::readLogicalDiskAligned(Communication& com, device_eventhandler_t report, + uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout) { + static std::shared_ptr NeoMemorySDRead = std::make_shared(Network::NetID::NeoMemorySDRead); + + if(amount != SectorSize) + return 0; + + const uint64_t currentSector = pos / SectorSize; + auto msg = com.waitForMessageSync([¤tSector, &com] { + return com.sendCommand(Command::NeoReadMemory, { + MemoryTypeSD, + uint8_t(currentSector & 0xFF), + uint8_t((currentSector >> 8) & 0xFF), + uint8_t((currentSector >> 16) & 0xFF), + uint8_t((currentSector >> 24) & 0xFF), + uint8_t(SectorSize & 0xFF), + uint8_t((SectorSize >> 8) & 0xFF), + uint8_t((SectorSize >> 16) & 0xFF), + uint8_t((SectorSize >> 24) & 0xFF) + }); + }, NeoMemorySDRead, timeout); + + if(!msg) + return 0; + + const auto sdmsg = std::dynamic_pointer_cast(msg); + if(!sdmsg || sdmsg->data.size() != SectorSize) { + report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error); + return nullopt; + } + + memcpy(into, sdmsg->data.data(), SectorSize); + return SectorSize; +} \ No newline at end of file diff --git a/disk/nulldiskreaddriver.cpp b/disk/nulldiskreaddriver.cpp index b8e96c4..682d9c9 100644 --- a/disk/nulldiskreaddriver.cpp +++ b/disk/nulldiskreaddriver.cpp @@ -2,14 +2,14 @@ using namespace icsneo; -optional NullDiskReadDriver::readLogicalDisk(Communication& com, device_eventhandler_t report, - uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout) { +optional NullDiskReadDriver::readLogicalDisk(Communication&, device_eventhandler_t report, + uint64_t, uint8_t*, uint64_t, std::chrono::milliseconds) { report(APIEvent::Type::DiskNotSupported, APIEvent::Severity::Error); - return std::nullopt; + return nullopt; } -optional NullDiskReadDriver::readLogicalDiskAligned(Communication& com, device_eventhandler_t report, - uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout) { +optional NullDiskReadDriver::readLogicalDiskAligned(Communication&, device_eventhandler_t report, + uint64_t, uint8_t*, uint64_t, std::chrono::milliseconds) { report(APIEvent::Type::DiskNotSupported, APIEvent::Severity::Error); - return std::nullopt; + return nullopt; } \ No newline at end of file diff --git a/include/icsneo/communication/command.h b/include/icsneo/communication/command.h index d08f96a..cbc09ed 100644 --- a/include/icsneo/communication/command.h +++ b/include/icsneo/communication/command.h @@ -8,6 +8,7 @@ namespace icsneo { enum class Command : uint8_t { EnableNetworkCommunication = 0x07, EnableNetworkCommunicationEx = 0x08, + NeoReadMemory = 0x40, RequestSerialNumber = 0xA1, GetMainVersion = 0xA3, // Previously known as RED_CMD_APP_VERSION_REQ SetSettings = 0xA4, // Previously known as RED_CMD_SET_BAUD_REQ, follow up with SaveSettings to write to EEPROM diff --git a/include/icsneo/communication/message/neoreadmemorysdmessage.h b/include/icsneo/communication/message/neoreadmemorysdmessage.h new file mode 100644 index 0000000..bf9bfcc --- /dev/null +++ b/include/icsneo/communication/message/neoreadmemorysdmessage.h @@ -0,0 +1,20 @@ +#ifndef __READMEMORYMESSAGE_H_ +#define __READMEMORYMESSAGE_H_ + +#ifdef __cplusplus + +#include "icsneo/communication/message/message.h" + +namespace icsneo { + +class NeoReadMemorySDMessage : public RawMessage { +public: + NeoReadMemorySDMessage() : RawMessage(Message::Type::RawMessage, Network::NetID::NeoMemorySDRead) {} + uint32_t startAddress = 0; +}; + +} + +#endif // __cplusplus + +#endif \ No newline at end of file diff --git a/include/icsneo/communication/network.h b/include/icsneo/communication/network.h index 80c3f8e..73ab8dd 100644 --- a/include/icsneo/communication/network.h +++ b/include/icsneo/communication/network.h @@ -41,7 +41,7 @@ public: RED_EXT_MEMORYREAD = 20, RED_INT_MEMORYREAD = 21, RED_DFLASH_READ = 22, - RED_SDCARD_READ = 23, + NeoMemorySDRead = 23, // Response from NeoMemory (MemoryTypeSD) CAN_ERRBITS = 24, RED_DFLASH_WRITE_DONE = 25, RED_WAVE_CAN1_LOGICAL = 26, @@ -272,6 +272,7 @@ public: case NetID::Main51: case NetID::ReadSettings: case NetID::EthPHYControl: + case NetID::NeoMemorySDRead: return Type::Internal; case NetID::Invalid: case NetID::Any: @@ -360,8 +361,8 @@ public: return "RED_INT_MEMORYREAD"; case NetID::RED_DFLASH_READ: return "RED_DFLASH_READ"; - case NetID::RED_SDCARD_READ: - return "RED_SDCARD_READ"; + case NetID::NeoMemorySDRead: + return "NeoMemorySDRead"; case NetID::CAN_ERRBITS: return "CAN_ERRBITS"; case NetID::RED_DFLASH_WRITE_DONE: diff --git a/include/icsneo/disk/neomemorydiskreaddriver.h b/include/icsneo/disk/neomemorydiskreaddriver.h new file mode 100644 index 0000000..820c295 --- /dev/null +++ b/include/icsneo/disk/neomemorydiskreaddriver.h @@ -0,0 +1,35 @@ +#ifndef __NEOMEMORYDISKREADDRIVER_H__ +#define __NEOMEMORYDISKREADDRIVER_H__ + +#ifdef __cplusplus + +#include "icsneo/disk/diskreaddriver.h" +#include + +namespace icsneo { + +/** + * A disk read driver which uses the neoMemory command to read from the disk + * + * This can only request reads by sector, so it will be very slow, but is likely supported by any device with a disk + */ +class NeoMemoryDiskReadDriver : public DiskReadDriver { +public: + Access getAccess() const override { return Access::VSA; } + 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"); + return { static_cast(SectorSize), static_cast(SectorSize) }; + } + +private: + static constexpr const uint8_t MemoryTypeSD = 0x01; // Logical Disk + + optional readLogicalDiskAligned(Communication& com, device_eventhandler_t report, + uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout) override; +}; + +} + +#endif // __cplusplus +#endif // __NEOMEMORYDISKREADDRIVER_H__ \ No newline at end of file diff --git a/include/icsneo/disk/nulldiskreaddriver.h b/include/icsneo/disk/nulldiskreaddriver.h index 2f5047c..2edc6e6 100644 --- a/include/icsneo/disk/nulldiskreaddriver.h +++ b/include/icsneo/disk/nulldiskreaddriver.h @@ -4,6 +4,7 @@ #ifdef __cplusplus #include "icsneo/disk/diskreaddriver.h" +#include namespace icsneo { @@ -17,7 +18,11 @@ public: optional readLogicalDisk(Communication& com, device_eventhandler_t report, uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout = DefaultTimeout) override; Access getAccess() const override { return Access::None; } - std::pair getBlockSizeBounds() const override { return {SectorSize, SectorSize}; } + 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"); + return { static_cast(SectorSize), static_cast(SectorSize) }; + } private: optional readLogicalDiskAligned(Communication& com, device_eventhandler_t report,