Disk: NeoMemory: Implement writing
parent
f05fd5e201
commit
f367fcecca
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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([¤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<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([¤tSector, &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;
|
||||
}
|
||||
|
|
@ -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([¤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<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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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__
|
||||
Loading…
Reference in New Issue