Device: Add readCoreminiHeader()
- Fixes NeoMemoryDiskDriver::readLogicalDiskAligned() for flash - Adds FlashMemoryMessageks-refactor-docs
parent
cac8d760b0
commit
564933cb41
|
|
@ -5,6 +5,7 @@
|
||||||
#include "icsneo/communication/message/readsettingsmessage.h"
|
#include "icsneo/communication/message/readsettingsmessage.h"
|
||||||
#include "icsneo/communication/message/canerrorcountmessage.h"
|
#include "icsneo/communication/message/canerrorcountmessage.h"
|
||||||
#include "icsneo/communication/message/neoreadmemorysdmessage.h"
|
#include "icsneo/communication/message/neoreadmemorysdmessage.h"
|
||||||
|
#include "icsneo/communication/message/flashmemorymessage.h"
|
||||||
#include "icsneo/communication/message/extendedresponsemessage.h"
|
#include "icsneo/communication/message/extendedresponsemessage.h"
|
||||||
#include "icsneo/communication/message/wiviresponsemessage.h"
|
#include "icsneo/communication/message/wiviresponsemessage.h"
|
||||||
#include "icsneo/communication/message/scriptstatusmessage.h"
|
#include "icsneo/communication/message/scriptstatusmessage.h"
|
||||||
|
|
@ -257,6 +258,18 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||||
result = std::make_shared<RawMessage>(packet->network, packet->data);
|
result = std::make_shared<RawMessage>(packet->network, packet->data);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case Network::NetID::RED_INT_MEMORYREAD: {
|
||||||
|
if(packet->data.size() != 512 + sizeof(uint16_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<FlashMemoryMessage>();
|
||||||
|
result = msg;
|
||||||
|
msg->startAddress = *reinterpret_cast<uint16_t*>(packet->data.data());
|
||||||
|
msg->data.insert(msg->data.end(), packet->data.begin() + 2, packet->data.end());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
case Network::NetID::NeoMemorySDRead: {
|
case Network::NetID::NeoMemorySDRead: {
|
||||||
if(packet->data.size() != 512 + sizeof(uint32_t)) {
|
if(packet->data.size() != 512 + sizeof(uint32_t)) {
|
||||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||||
|
|
|
||||||
|
|
@ -656,6 +656,85 @@ bool Device::clearScript(Disk::MemoryType memType)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<CoreminiHeader> Device::readCoreminiHeader(Disk::MemoryType memType) {
|
||||||
|
if(!isOpen()) {
|
||||||
|
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto startAddress = getCoreminiStartAddress(memType);
|
||||||
|
if(!startAddress) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto connected = isLogicalDiskConnected();
|
||||||
|
|
||||||
|
if(!connected) {
|
||||||
|
return std::nullopt; // Already added an API error
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma pack(push, 2)
|
||||||
|
struct RawCoreminiHeader {
|
||||||
|
uint16_t fileType;
|
||||||
|
uint16_t fileVersion;
|
||||||
|
uint32_t storedFileSize;
|
||||||
|
uint32_t fileChecksum;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint32_t skipDecompression : 1;
|
||||||
|
uint32_t encryptedMode : 1;
|
||||||
|
uint32_t reserved : 30;
|
||||||
|
} bits;
|
||||||
|
uint32_t word;
|
||||||
|
} flags;
|
||||||
|
uint8_t fileHash[32];
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint32_t lsb;
|
||||||
|
uint32_t msb;
|
||||||
|
} words;
|
||||||
|
uint64_t time64;
|
||||||
|
} createTime;
|
||||||
|
uint8_t reserved[8];
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
RawCoreminiHeader header = {};
|
||||||
|
auto numRead = readLogicalDisk(*startAddress, (uint8_t*)&header, sizeof(header), std::chrono::milliseconds(2000), memType);
|
||||||
|
|
||||||
|
if(!numRead) {
|
||||||
|
return std::nullopt; // Already added an API error
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*numRead != sizeof(header)) {
|
||||||
|
report(APIEvent::Type::FailedToRead, APIEvent::Severity::Error);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(header.fileType != 0x0907) {
|
||||||
|
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<CoreminiHeader> ret;
|
||||||
|
ret.emplace();
|
||||||
|
ret->coreminiVersion = header.fileVersion;
|
||||||
|
ret->storedFileSize = header.storedFileSize;
|
||||||
|
ret->fileChecksum = header.fileChecksum;
|
||||||
|
ret->skipDecompression = static_cast<bool>(header.flags.bits.skipDecompression);
|
||||||
|
ret->encryptedMode = static_cast<bool>(header.flags.bits.encryptedMode);
|
||||||
|
std::copy(std::begin(header.fileHash), std::end(header.fileHash), ret->fileHash.begin());
|
||||||
|
static constexpr std::chrono::seconds icsEpochDelta(1167609600);
|
||||||
|
static constexpr uint8_t timestampResolution = 25;
|
||||||
|
static constexpr uint16_t nsInUs = 1'000;
|
||||||
|
ret->timestamp += icsEpochDelta + std::chrono::microseconds(header.createTime.time64 * timestampResolution / nsInUs);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bool Device::transmit(std::shared_ptr<Frame> frame) {
|
bool Device::transmit(std::shared_ptr<Frame> frame) {
|
||||||
if(!isOpen()) {
|
if(!isOpen()) {
|
||||||
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
|
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include "icsneo/disk/neomemorydiskdriver.h"
|
#include "icsneo/disk/neomemorydiskdriver.h"
|
||||||
#include "icsneo/communication/message/neoreadmemorysdmessage.h"
|
#include "icsneo/communication/message/neoreadmemorysdmessage.h"
|
||||||
|
#include "icsneo/communication/message/flashmemorymessage.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
@ -8,7 +9,8 @@ using namespace icsneo::Disk;
|
||||||
|
|
||||||
std::optional<uint64_t> NeoMemoryDiskDriver::readLogicalDiskAligned(Communication& com, device_eventhandler_t report,
|
std::optional<uint64_t> NeoMemoryDiskDriver::readLogicalDiskAligned(Communication& com, device_eventhandler_t report,
|
||||||
uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout, MemoryType memType) {
|
uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout, MemoryType memType) {
|
||||||
static std::shared_ptr<MessageFilter> NeoMemorySDRead = std::make_shared<MessageFilter>(Network::NetID::NeoMemorySDRead);
|
const auto filter = std::make_shared<MessageFilter>((memType == MemoryType::SD ? Network::NetID::NeoMemorySDRead : Network::NetID::RED_INT_MEMORYREAD));
|
||||||
|
filter->includeInternalInAny = true;
|
||||||
|
|
||||||
if(pos % SectorSize != 0)
|
if(pos % SectorSize != 0)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
@ -33,18 +35,26 @@ std::optional<uint64_t> NeoMemoryDiskDriver::readLogicalDiskAligned(Communicatio
|
||||||
uint8_t((numWords >> 16) & 0xFF),
|
uint8_t((numWords >> 16) & 0xFF),
|
||||||
uint8_t((numWords >> 24) & 0xFF)
|
uint8_t((numWords >> 24) & 0xFF)
|
||||||
});
|
});
|
||||||
}, NeoMemorySDRead, timeout);
|
}, filter, timeout);
|
||||||
|
|
||||||
if(!msg)
|
if(!msg)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const auto sdmsg = std::dynamic_pointer_cast<NeoReadMemorySDMessage>(msg);
|
if(memType == MemoryType::SD) {
|
||||||
if(!sdmsg || sdmsg->data.size() != SectorSize) {
|
const auto mem = std::dynamic_pointer_cast<NeoReadMemorySDMessage>(msg);
|
||||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
if(!mem || mem->data.size() != SectorSize) {
|
||||||
return std::nullopt;
|
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
memcpy(into, mem->data.data(), SectorSize);
|
||||||
|
} else { // flash
|
||||||
|
const auto mem = std::dynamic_pointer_cast<FlashMemoryMessage>(msg);
|
||||||
|
if(!mem || mem->data.size() != SectorSize) {
|
||||||
|
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
memcpy(into, mem->data.data(), SectorSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(into, sdmsg->data.data(), SectorSize);
|
|
||||||
return SectorSize;
|
return SectorSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef __FLASHMEMORYMESSAGE_H_
|
||||||
|
#define __FLASHMEMORYMESSAGE_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include "icsneo/communication/message/message.h"
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
class FlashMemoryMessage : public RawMessage {
|
||||||
|
public:
|
||||||
|
FlashMemoryMessage() : RawMessage(Message::Type::RawMessage, Network::NetID::RED_INT_MEMORYREAD) {}
|
||||||
|
uint16_t startAddress = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -533,6 +533,7 @@ public:
|
||||||
case NetID::CoreMiniPreLoad:
|
case NetID::CoreMiniPreLoad:
|
||||||
case NetID::ExtendedCommand:
|
case NetID::ExtendedCommand:
|
||||||
case NetID::ExtendedData:
|
case NetID::ExtendedData:
|
||||||
|
case NetID::RED_INT_MEMORYREAD:
|
||||||
case NetID::NeoMemorySDRead:
|
case NetID::NeoMemorySDRead:
|
||||||
case NetID::NeoMemoryWriteDone:
|
case NetID::NeoMemoryWriteDone:
|
||||||
case NetID::RED_GET_RTC:
|
case NetID::RED_GET_RTC:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef __COREMINI_H_
|
||||||
|
#define __COREMINI_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <array>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
struct CoreminiHeader {
|
||||||
|
uint16_t coreminiVersion;
|
||||||
|
uint32_t storedFileSize;
|
||||||
|
// 32-bit word checksum on the entire (decompressed) binary, with the checksum and hash fields set to 0
|
||||||
|
uint32_t fileChecksum;
|
||||||
|
// SHA256 hash of the entire (decompressed) binary, with the checksum, hash, and create time fields set to 0
|
||||||
|
bool skipDecompression;
|
||||||
|
bool encryptedMode;
|
||||||
|
std::array<uint8_t, 32> fileHash;
|
||||||
|
std::chrono::time_point<std::chrono::system_clock> timestamp;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <chrono>
|
||||||
#include "icsneo/api/eventmanager.h"
|
#include "icsneo/api/eventmanager.h"
|
||||||
#include "icsneo/api/lifetime.h"
|
#include "icsneo/api/lifetime.h"
|
||||||
#include "icsneo/device/neodevice.h"
|
#include "icsneo/device/neodevice.h"
|
||||||
|
|
@ -21,6 +22,7 @@
|
||||||
#include "icsneo/device/devicetype.h"
|
#include "icsneo/device/devicetype.h"
|
||||||
#include "icsneo/device/deviceversion.h"
|
#include "icsneo/device/deviceversion.h"
|
||||||
#include "icsneo/device/founddevice.h"
|
#include "icsneo/device/founddevice.h"
|
||||||
|
#include "icsneo/device/coremini.h"
|
||||||
#include "icsneo/disk/diskreaddriver.h"
|
#include "icsneo/disk/diskreaddriver.h"
|
||||||
#include "icsneo/disk/diskwritedriver.h"
|
#include "icsneo/disk/diskwritedriver.h"
|
||||||
#include "icsneo/disk/nulldiskdriver.h"
|
#include "icsneo/disk/nulldiskdriver.h"
|
||||||
|
|
@ -163,6 +165,7 @@ public:
|
||||||
bool stopScript();
|
bool stopScript();
|
||||||
bool clearScript(Disk::MemoryType memType = Disk::MemoryType::SD);
|
bool clearScript(Disk::MemoryType memType = Disk::MemoryType::SD);
|
||||||
bool uploadCoremini(std::istream& stream, Disk::MemoryType memType = Disk::MemoryType::SD);
|
bool uploadCoremini(std::istream& stream, Disk::MemoryType memType = Disk::MemoryType::SD);
|
||||||
|
std::optional<CoreminiHeader> readCoreminiHeader(Disk::MemoryType memType = Disk::MemoryType::SD);
|
||||||
|
|
||||||
bool eraseScriptMemory(Disk::MemoryType memType, uint64_t amount);
|
bool eraseScriptMemory(Disk::MemoryType memType, uint64_t amount);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue