diff --git a/CMakeLists.txt b/CMakeLists.txt index 45ac0a2..a85f0ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -249,6 +249,7 @@ set(SRC_FILES communication/packet/scriptstatuspacket.cpp communication/packet/componentversionpacket.cpp communication/packet/supportedfeaturespacket.cpp + communication/packet/genericbinarystatuspacket.cpp communication/decoder.cpp communication/encoder.cpp communication/ethernetpacketizer.cpp diff --git a/communication/decoder.cpp b/communication/decoder.cpp index ecb6392..45a892a 100644 --- a/communication/decoder.cpp +++ b/communication/decoder.cpp @@ -13,6 +13,7 @@ #include "icsneo/communication/message/i2cmessage.h" #include "icsneo/communication/message/linmessage.h" #include "icsneo/communication/message/mdiomessage.h" +#include "icsneo/communication/message/extendeddatamessage.h" #include "icsneo/communication/command.h" #include "icsneo/device/device.h" #include "icsneo/communication/packet/canpacket.h" @@ -30,6 +31,7 @@ #include "icsneo/communication/packet/componentversionpacket.h" #include "icsneo/communication/packet/supportedfeaturespacket.h" #include "icsneo/communication/packet/mdiopacket.h" +#include "icsneo/communication/packet/genericbinarystatuspacket.h" #include using namespace icsneo; @@ -259,6 +261,7 @@ bool Decoder::decode(std::shared_ptr& result, const std::shared_ptrdata.size() < sizeof(ExtendedResponseMessage::PackedGenericResponse)) break; // Handle as a raw message, might not be a generic response @@ -266,18 +269,44 @@ bool Decoder::decode(std::shared_ptr& result, const std::shared_ptrdata); - return true; + return true; case ExtendedCommand::GetSupportedFeatures: result = SupportedFeaturesPacket::DecodeToMessage(packet->data); return true; + case ExtendedCommand::GenericBinaryInfo: + result = GenericBinaryStatusPacket::DecodeToMessage(packet->data); + return true; case ExtendedCommand::GenericReturn: result = std::make_shared(resp.command, resp.returnCode); return true; default: // No defined handler, treat this as a RawMessage break; + } + break; + } + case Network::NetID::ExtendedData: { + if(packet->data.size() < sizeof(ExtendedDataMessage::ExtendedDataHeader)) + break; + + const auto& header = *reinterpret_cast(packet->data.data()); + + switch(header.subCommand) { + case ExtendedDataSubCommand::GenericBinaryRead: { + result = std::make_shared(header); + auto extDataMsg = std::static_pointer_cast(result); + + size_t numRead = std::min(ExtendedDataMessage::MaxExtendedDataBufferSize, (size_t)header.length); + extDataMsg->data.resize(numRead); + + std::copy(packet->data.begin() + sizeof(header), packet->data.begin() + sizeof(header) + numRead, extDataMsg->data.begin()); + return true; + } + default: + break; + } + break; } - } break; case Network::NetID::FlexRayControl: { auto frResult = std::make_shared(*packet); if(!frResult->decoded) { diff --git a/communication/packet/genericbinarystatuspacket.cpp b/communication/packet/genericbinarystatuspacket.cpp new file mode 100644 index 0000000..a9b4283 --- /dev/null +++ b/communication/packet/genericbinarystatuspacket.cpp @@ -0,0 +1,38 @@ +#include "icsneo/communication/packet/genericbinarystatuspacket.h" +#include "icsneo/communication/message/genericbinarystatusmessage.h" + +using namespace icsneo; + +#pragma pack(push, 2) +struct GenericBinaryStatusResponse { + ExtendedResponseMessage::ResponseHeader header; + size_t size; + uint16_t index; + uint16_t status; +}; +#pragma pack(pop) + +std::shared_ptr GenericBinaryStatusPacket::DecodeToMessage(const std::vector& bytes) { + if(bytes.size() < sizeof(GenericBinaryStatusResponse)) { + return nullptr; + } + + auto msg = std::make_shared(); + + const auto& response = *reinterpret_cast(bytes.data()); + + msg->binarySize = response.size; + msg->binaryIndex = response.index; + msg->binaryStatus = response.status; + + return msg; +} + +std::vector GenericBinaryStatusPacket::EncodeArguments(uint16_t binaryIndex) { + std::vector bytestream(sizeof(GenericBinaryStatusResponse)); + + auto& parameters = *reinterpret_cast(bytestream.data()); + parameters.index = binaryIndex; + + return bytestream; +} diff --git a/device/device.cpp b/device/device.cpp index e1db9fb..819f9e8 100644 --- a/device/device.cpp +++ b/device/device.cpp @@ -1780,3 +1780,78 @@ std::optional> Device::getSupportedFeatures() { } return std::move(typedResponse->features); } + +std::optional Device::getGenericBinarySize(uint16_t binaryIndex) { + auto timeout = std::chrono::milliseconds(2000); + + if(!isOpen()) { + report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error); + return std::nullopt; + } + + if(!isOnline()) { + report(APIEvent::Type::DeviceCurrentlyOffline, APIEvent::Severity::Error); + return std::nullopt; + } + + std::vector args = GenericBinaryStatusPacket::EncodeArguments(binaryIndex); + + std::shared_ptr response = com->waitForMessageSync( + [this, &args](){ + return com->sendCommand(ExtendedCommand::GenericBinaryInfo, args); + }, + std::make_shared(Message::Type::GenericBinaryStatus), + timeout + ); + + if(!response) { + report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error); + return std::nullopt; + } + auto retMsg = std::static_pointer_cast(response); + if(!retMsg) { + return std::nullopt; + } + + return retMsg->binarySize; +} + +bool Device::readBinaryFile(std::ostream& stream, uint16_t binaryIndex) { + auto timeout = std::chrono::milliseconds(100); + + auto size = getGenericBinarySize(binaryIndex); + + if(!size) { + return false; + } + + std::vector arguments(sizeof(ExtendedDataMessage::ExtendedDataHeader)); + ExtendedDataMessage::ExtendedDataHeader& parameters = *reinterpret_cast(arguments.data()); + + auto filter = std::make_shared(Network::NetID::ExtendedData); + + for(size_t offset = 0; offset < *size; offset+=ExtendedDataMessage::MaxExtendedDataBufferSize) { + parameters.subCommand = ExtendedDataSubCommand::GenericBinaryRead; + parameters.userValue = static_cast(binaryIndex); + parameters.offset = static_cast(offset); + parameters.length = static_cast(std::min(ExtendedDataMessage::MaxExtendedDataBufferSize, *size - offset)); + + std::shared_ptr response = com->waitForMessageSync( + [this, arguments](){ + return com->sendCommand(Command::ExtendedData, arguments); + }, + filter, + timeout + ); + if(!response) { + report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error); + return false; + } + auto retMsg = std::static_pointer_cast(response); + + if(!stream.write(reinterpret_cast(retMsg->data.data()), retMsg->data.size())) { + return false; + } + } + return true; +} \ No newline at end of file diff --git a/include/icsneo/communication/command.h b/include/icsneo/communication/command.h index c1ac504..f931e21 100644 --- a/include/icsneo/communication/command.h +++ b/include/icsneo/communication/command.h @@ -31,7 +31,8 @@ enum class Command : uint8_t { GetVBattReq = 0xDF, // Previously known as RED_CMD_VBATT_REQUEST ScriptStatus = 0xE0, // Previously known as RED_CMD_SCRIPT_STATUS MiscControl = 0xE7, - Extended = 0xF0, + Extended = 0xF0, // Previously known as RED_CMD_EXT_COMM + ExtendedData = 0xF2, // Previously known as RED_CMD_EXTENDED_DATA FlexRayControl = 0xF3, CoreMiniPreload = 0xF4, // Previously known as RED_CMD_COREMINI_PRELOAD PHYControlRegisters = 0xEF @@ -51,6 +52,7 @@ enum class ExtendedCommand : uint16_t { GetComponentVersions = 0x001A, Reboot = 0x001C, SetUploadedFlag = 0x0027, + GenericBinaryInfo = 0x0030, }; enum class ExtendedResponse : int32_t { @@ -62,6 +64,10 @@ enum class ExtendedResponse : int32_t { InvalidParameter = -5, }; +enum class ExtendedDataSubCommand : uint32_t { + GenericBinaryRead = 13, +}; + } #endif // __cplusplus diff --git a/include/icsneo/communication/message/extendeddatamessage.h b/include/icsneo/communication/message/extendeddatamessage.h new file mode 100644 index 0000000..137267f --- /dev/null +++ b/include/icsneo/communication/message/extendeddatamessage.h @@ -0,0 +1,34 @@ +#ifndef __EXTENDEDDATAMESSAGE_H_ +#define __EXTENDEDDATAMESSAGE_H_ + +#ifdef __cplusplus + +#include "icsneo/communication/message/message.h" +#include "icsneo/communication/command.h" + + +namespace icsneo { + +class ExtendedDataMessage : public RawMessage { +public: + #pragma pack(push, 2) + struct ExtendedDataHeader { + ExtendedDataSubCommand subCommand; + uint32_t userValue; + uint32_t offset; + uint32_t length; + }; + #pragma pack(pop) + + static constexpr size_t MaxExtendedDataBufferSize = 2048; + const ExtendedDataHeader header; + + ExtendedDataMessage(ExtendedDataHeader params) : RawMessage(Message::Type::RawMessage, Network::NetID::ExtendedData), header{params} {} + +}; + +} + +#endif // __cplusplus + +#endif \ No newline at end of file diff --git a/include/icsneo/communication/message/genericbinarystatusmessage.h b/include/icsneo/communication/message/genericbinarystatusmessage.h new file mode 100644 index 0000000..a303a31 --- /dev/null +++ b/include/icsneo/communication/message/genericbinarystatusmessage.h @@ -0,0 +1,22 @@ +#ifndef _EXTENDED_GENERIC_BINARY_STATUS_MESSAGE_H_ +#define _EXTENDED_GENERIC_BINARY_STATUS_MESSAGE_H_ + +#ifdef __cplusplus +#include "icsneo/communication/message/extendedresponsemessage.h" + +namespace icsneo { + +class GenericBinaryStatusMessage : public Message { +public: + GenericBinaryStatusMessage() : Message(Message::Type::GenericBinaryStatus) {} + + size_t binarySize; + uint16_t binaryIndex; + uint16_t binaryStatus; +}; + +} + +#endif // __cplusplus + +#endif // _EXTENDED_GENERIC_BINARY_STATUS_RESPONSE_MESSAGE_H_ \ No newline at end of file diff --git a/include/icsneo/communication/message/message.h b/include/icsneo/communication/message/message.h index d803465..a91d96b 100644 --- a/include/icsneo/communication/message/message.h +++ b/include/icsneo/communication/message/message.h @@ -36,6 +36,7 @@ public: ScriptStatus = 0x800b, ComponentVersions = 0x800c, SupportedFeatures = 0x800d, + GenericBinaryStatus = 0x800e, }; Message(Type t) : type(t) {} diff --git a/include/icsneo/communication/network.h b/include/icsneo/communication/network.h index 1e38eba..02676f0 100644 --- a/include/icsneo/communication/network.h +++ b/include/icsneo/communication/network.h @@ -123,6 +123,7 @@ public: ScriptStatus = 224, EthPHYControl = 239, ExtendedCommand = 240, + ExtendedData = 242, FlexRayControl = 243, CoreMiniPreLoad = 244, HW_COM_Latency_Test = 512, @@ -349,6 +350,7 @@ public: case NetID::EthPHYControl: case NetID::CoreMiniPreLoad: case NetID::ExtendedCommand: + case NetID::ExtendedData: case NetID::NeoMemorySDRead: case NetID::NeoMemoryWriteDone: case NetID::RED_GET_RTC: diff --git a/include/icsneo/communication/packet/genericbinarystatuspacket.h b/include/icsneo/communication/packet/genericbinarystatuspacket.h new file mode 100644 index 0000000..a3b02c0 --- /dev/null +++ b/include/icsneo/communication/packet/genericbinarystatuspacket.h @@ -0,0 +1,23 @@ +#ifndef __GENERICBINARYSTATUSPACKET_H__ +#define __GENERICBINARYSTATUSPACKET_H__ + +#ifdef __cplusplus + +#include +#include +#include + +namespace icsneo { + +class GenericBinaryStatusMessage; + +struct GenericBinaryStatusPacket { + static std::shared_ptr DecodeToMessage(const std::vector& bytes); + static std::vector EncodeArguments(uint16_t binaryIndex); +}; + +} + +#endif // __cplusplus + +#endif // __GENERICBINARYSTATUSPACKET_H__ diff --git a/include/icsneo/device/device.h b/include/icsneo/device/device.h index 39cc34e..c739e8f 100644 --- a/include/icsneo/device/device.h +++ b/include/icsneo/device/device.h @@ -33,6 +33,9 @@ #include "icsneo/communication/message/wiviresponsemessage.h" #include "icsneo/communication/message/scriptstatusmessage.h" #include "icsneo/communication/message/supportedfeaturesmessage.h" +#include "icsneo/communication/message/genericbinarystatusmessage.h" +#include "icsneo/communication/message/extendeddatamessage.h" +#include "icsneo/communication/packet/genericbinarystatuspacket.h" #include "icsneo/device/extensions/flexray/controller.h" #include "icsneo/communication/message/flexray/control/flexraycontrolmessage.h" #include "icsneo/communication/message/ethphymessage.h" @@ -565,6 +568,9 @@ public: std::shared_ptr com; std::unique_ptr settings; + std::optional getGenericBinarySize(uint16_t binaryIndex); + bool readBinaryFile(std::ostream& stream, uint16_t binaryIndex); + protected: bool online = false; int messagePollingCallbackID = 0; @@ -670,6 +676,8 @@ protected: neodevice_t& getWritableNeoDevice() { return data; } + + private: neodevice_t data; std::shared_ptr latestResetStatus;