Disk: NeoMemory: Implement writing

v0.3.0-dev
Paul Hollinsky 2022-03-03 20:26:56 -05:00
parent f05fd5e201
commit f367fcecca
8 changed files with 114 additions and 62 deletions

View File

@ -152,7 +152,7 @@ set(SRC_FILES
disk/diskreaddriver.cpp
disk/diskwritedriver.cpp
disk/nulldiskdriver.cpp
disk/neomemorydiskreaddriver.cpp
disk/neomemorydiskdriver.cpp
disk/plasiondiskreaddriver.cpp
disk/extextractordiskreaddriver.cpp
disk/fat.cpp

View File

@ -0,0 +1,92 @@
#include "icsneo/disk/neomemorydiskdriver.h"
#include "icsneo/communication/message/neoreadmemorysdmessage.h"
#include <cstring>
using namespace icsneo;
using namespace icsneo::Disk;
optional<uint64_t> NeoMemoryDiskDriver::readLogicalDiskAligned(Communication& com, device_eventhandler_t report,
uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout) {
static std::shared_ptr<MessageFilter> NeoMemorySDRead = std::make_shared<MessageFilter>(Network::NetID::NeoMemorySDRead);
if(pos % SectorSize != 0)
return nullopt;
if(amount != SectorSize)
return nullopt;
if(cachePos != pos || std::chrono::steady_clock::now() > cachedAt + CacheTime) {
// The cache does not have this data, go get it
const uint64_t currentSector = pos / SectorSize;
auto msg = com.waitForMessageSync([&currentSector, &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<NeoReadMemorySDMessage>(msg);
if(!sdmsg || sdmsg->data.size() != SectorSize) {
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
return nullopt;
}
memcpy(cache.data(), sdmsg->data.data(), SectorSize);
cachedAt = std::chrono::steady_clock::now();
cachePos = pos;
}
memcpy(into, cache.data(), SectorSize);
return SectorSize;
}
optional<uint64_t> NeoMemoryDiskDriver::writeLogicalDiskAligned(Communication& com, device_eventhandler_t report,
uint64_t pos, const uint8_t* atomicBuf, const uint8_t* from, uint64_t amount, std::chrono::milliseconds timeout) {
static std::shared_ptr<MessageFilter> NeoMemoryDone = std::make_shared<MessageFilter>(Network::NetID::NeoMemoryWriteDone);
if(pos % SectorSize != 0)
return nullopt;
if(amount != SectorSize)
return nullopt;
// Clear the cache if we're writing to the cached sector
if(pos == cachePos)
cachedAt = std::chrono::time_point<std::chrono::steady_clock>();
// Requesting an atomic operation, but neoMemory does not support it
// Continue on anyway but warn the caller
if(atomicBuf != nullptr)
report(APIEvent::Type::AtomicOperationCompletedNonatomically, NonatomicSeverity);
const uint64_t currentSector = pos / SectorSize;
auto msg = com.waitForMessageSync([&currentSector, &com, from, amount] {
std::vector<uint8_t> command = {
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),
};
command.insert(command.end(), from, from + amount);
return com.sendCommand(Command::NeoWriteMemory, command);
}, NeoMemoryDone, timeout);
if(!msg)
return nullopt;
return SectorSize;
}

View File

@ -1,48 +0,0 @@
#include "icsneo/disk/neomemorydiskreaddriver.h"
#include "icsneo/communication/message/neoreadmemorysdmessage.h"
#include <cstring>
using namespace icsneo;
using namespace icsneo::Disk;
optional<uint64_t> 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<MessageFilter> NeoMemorySDRead = std::make_shared<MessageFilter>(Network::NetID::NeoMemorySDRead);
if(amount != SectorSize)
return 0;
if(cachePos != pos || std::chrono::steady_clock::now() > cachedAt + CacheTime) {
// The cache does not have this data, go get it
const uint64_t currentSector = pos / SectorSize;
auto msg = com.waitForMessageSync([&currentSector, &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<NeoReadMemorySDMessage>(msg);
if(!sdmsg || sdmsg->data.size() != SectorSize) {
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
return nullopt;
}
memcpy(cache.data(), sdmsg->data.data(), SectorSize);
cachedAt = std::chrono::steady_clock::now();
cachePos = pos;
}
memcpy(into, cache.data(), SectorSize);
return SectorSize;
}

View File

@ -9,6 +9,7 @@ enum class Command : uint8_t {
EnableNetworkCommunication = 0x07,
EnableNetworkCommunicationEx = 0x08,
NeoReadMemory = 0x40,
NeoWriteMemory = 0x41,
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

View File

@ -43,7 +43,7 @@ public:
RED_DFLASH_READ = 22,
NeoMemorySDRead = 23, // Response from NeoMemory (MemoryTypeSD)
CAN_ERRBITS = 24,
RED_DFLASH_WRITE_DONE = 25,
NeoMemoryWriteDone = 25,
RED_WAVE_CAN1_LOGICAL = 26,
RED_WAVE_CAN2_LOGICAL = 27,
RED_WAVE_LIN1_LOGICAL = 28,
@ -275,6 +275,7 @@ public:
case NetID::LogicalDiskInfo:
case NetID::EthPHYControl:
case NetID::NeoMemorySDRead:
case NetID::NeoMemoryWriteDone:
return Type::Internal;
case NetID::Invalid:
case NetID::Any:
@ -367,8 +368,8 @@ public:
return "NeoMemorySDRead";
case NetID::CAN_ERRBITS:
return "CAN_ERRBITS";
case NetID::RED_DFLASH_WRITE_DONE:
return "RED_DFLASH_WRITE_DONE";
case NetID::NeoMemoryWriteDone:
return "NeoMemoryWriteDone";
case NetID::RED_WAVE_CAN1_LOGICAL:
return "RED_WAVE_CAN1_LOGICAL";
case NetID::RED_WAVE_CAN2_LOGICAL:
@ -835,9 +836,9 @@ private:
#define ICSNEO_NETID_RED_EXT_MEMORYREAD 20
#define ICSNEO_NETID_RED_INT_MEMORYREAD 21
#define ICSNEO_NETID_RED_DFLASH_READ 22
#define ICSNEO_NETID_RED_SDCARD_READ 23
#define ICSNEO_NETID_NEOMEMORY_SD_READ 23
#define ICSNEO_NETID_CAN_ERRBITS 24
#define ICSNEO_NETID_RED_DFLASH_WRITE_DONE 25
#define ICSNEO_NETID_NEOMEMORY_WRITE_DONE 25
#define ICSNEO_NETID_RED_WAVE_CAN1_LOGICAL 26
#define ICSNEO_NETID_RED_WAVE_CAN2_LOGICAL 27
#define ICSNEO_NETID_RED_WAVE_LIN1_LOGICAL 28

View File

@ -5,6 +5,7 @@
#include "icsneo/device/devicetype.h"
#include "icsneo/platform/pcap.h"
#include "icsneo/disk/extextractordiskreaddriver.h"
#include "icsneo/disk/neomemorydiskdriver.h"
#include "icsneo/device/tree/neovired2/neovired2settings.h"
namespace icsneo {
@ -68,7 +69,7 @@ public:
protected:
NeoVIRED2(neodevice_t neodevice) : Device(neodevice) {
initialize<PCAP, NeoVIRED2Settings, Disk::ExtExtractorDiskReadDriver>();
initialize<PCAP, NeoVIRED2Settings, Disk::ExtExtractorDiskReadDriver, Disk::NeoMemoryDiskDriver>();
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
}

View File

@ -7,6 +7,7 @@
#include "icsneo/device/devicetype.h"
#include "icsneo/platform/ftdi.h"
#include "icsneo/disk/plasiondiskreaddriver.h"
#include "icsneo/disk/neomemorydiskdriver.h"
namespace icsneo {
@ -25,7 +26,7 @@ public:
private:
NeoVIION(neodevice_t neodevice) : Plasion(neodevice) {
initialize<FTDI, NullSettings, Disk::PlasionDiskReadDriver>();
initialize<FTDI, NullSettings, Disk::PlasionDiskReadDriver, Disk::NeoMemoryDiskDriver>();
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
}

View File

@ -1,9 +1,10 @@
#ifndef __NEOMEMORYDISKREADDRIVER_H__
#define __NEOMEMORYDISKREADDRIVER_H__
#ifndef __NEOMEMORYDISKDRIVER_H__
#define __NEOMEMORYDISKDRIVER_H__
#ifdef __cplusplus
#include "icsneo/disk/diskreaddriver.h"
#include "icsneo/disk/diskwritedriver.h"
#include <limits>
#include <chrono>
@ -12,11 +13,11 @@ namespace icsneo {
namespace Disk {
/**
* A disk read driver which uses the neoMemory command to read from the disk
* A disk driver which uses the neoMemory command to read from or write to 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
* This can only make requests per sector, so it will be very slow, but is likely supported by any device with a disk
*/
class NeoMemoryDiskReadDriver : public ReadDriver {
class NeoMemoryDiskDriver : public ReadDriver, public WriteDriver {
public:
std::pair<uint32_t, uint32_t> getBlockSizeBounds() const override {
static_assert(SectorSize <= std::numeric_limits<uint32_t>::max(), "Incorrect sector size");
@ -36,6 +37,9 @@ private:
optional<uint64_t> readLogicalDiskAligned(Communication& com, device_eventhandler_t report,
uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout) override;
optional<uint64_t> writeLogicalDiskAligned(Communication& com, device_eventhandler_t report,
uint64_t pos, const uint8_t* atomicBuf, const uint8_t* from, uint64_t amount, std::chrono::milliseconds timeout) override;
};
} // namespace Disk
@ -43,4 +47,4 @@ private:
} // namespace icsneo
#endif // __cplusplus
#endif // __NEOMEMORYDISKREADDRIVER_H__
#endif // __NEOMEMORYDISKDRIVER_H__