diff --git a/CMakeLists.txt b/CMakeLists.txt index c8d9f3f..da512d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -234,6 +234,7 @@ set(SRC_FILES communication/message/ethernetstatusmessage.cpp communication/message/networkmutexmessage.cpp communication/message/clientidmessage.cpp + communication/message/mfgconfigmessage.cpp communication/message/transmitmessage.cpp communication/message/spiportkeymessage.cpp communication/message/genericapidatamessage.cpp diff --git a/communication/decoder.cpp b/communication/decoder.cpp index 907dcc8..f086ab7 100644 --- a/communication/decoder.cpp +++ b/communication/decoder.cpp @@ -26,6 +26,7 @@ #include "icsneo/communication/message/ethernetstatusmessage.h" #include "icsneo/communication/message/networkmutexmessage.h" #include "icsneo/communication/message/clientidmessage.h" +#include "icsneo/communication/message/mfgconfigmessage.h" #include "icsneo/communication/message/spiportkeymessage.h" #include "icsneo/communication/message/genericapidatamessage.h" #include "icsneo/communication/message/genericapistatusmessage.h" @@ -371,6 +372,9 @@ bool Decoder::decode(std::shared_ptr& result, const std::shared_ptr + +using namespace icsneo; + +static MfgConfigMessage::VersionNumber versionFromProto(const settings::common::v1::VersionNumber& version) { + MfgConfigMessage::VersionNumber decoded; + decoded.major = version.major(); + decoded.minor = version.minor(); + if(version.has_release()) + decoded.release = version.release(); + if(version.has_build()) + decoded.build = version.build(); + return decoded; +} + +std::shared_ptr MfgConfigMessage::DecodeToMessage(const std::vector& bytestream) { + MfgConfigMessage decoded; + settings::manufacturing::v1::MfgConfig msg; + + if(!protoapi::processResponse(bytestream.data(), bytestream.size(), msg)) { + return nullptr; + } + + if(msg.has_serial_number()) { + decoded.serialNumber = msg.serial_number(); + } + if(msg.has_manufacture_date()) { + const auto& date = msg.manufacture_date(); + decoded.manufactureDate = MfgDate{date.manufacture_day(), date.manufacture_month(), date.manufacture_year()}; + } + if(msg.has_hardware_rev()) { + decoded.hardwareRev = versionFromProto(msg.hardware_rev()); + } + if(msg.has_product_id()) { + decoded.productId = static_cast(msg.product_id()); + } + if(msg.has_bootloader_rev()) { + decoded.bootloaderRev = versionFromProto(msg.bootloader_rev()); + } + if(msg.has_usb_descriptor()) { + decoded.usbDescriptor = msg.usb_descriptor(); + } + for(const auto& mac : msg.mac_addresses()) { + const auto& bytes = mac.mac_addr(); + if(bytes.size() < MACAddressLength) + continue; + MACAddress address{}; + std::copy_n(bytes.begin(), MACAddressLength, address.begin()); + decoded.macAddresses.push_back(address); + } + if(msg.has_pcb_serial()) { + decoded.pcbSerial = msg.pcb_serial().pcb_serial(); + } + if(msg.has_chip_id()) { + decoded.chipId = static_cast(msg.chip_id()); + } + if(msg.has_imei()) { + decoded.imei = msg.imei(); + } + if(msg.has_parent_product_id()) { + decoded.parentProductId = static_cast(msg.parent_product_id()); + } + if(msg.has_software_version_lock()) { + decoded.softwareVersionLock = versionFromProto(msg.software_version_lock()); + } + + return std::make_shared(decoded); +} + +std::vector MfgConfigMessage::EncodeArgumentsForGet() { + settings::manufacturing::v1::MfgConfig msg; + msg.Clear(); + return protoapi::getPayload(protoapi::Command::GET, msg); +} diff --git a/device/device.cpp b/device/device.cpp index f9138c3..767d0bb 100644 --- a/device/device.cpp +++ b/device/device.cpp @@ -8,6 +8,7 @@ #include "icsneo/disk/fat.h" #include "icsneo/communication/message/filter/extendedresponsefilter.h" #include "icsneo/communication/message/networkmutexmessage.h" +#include "icsneo/communication/message/mfgconfigmessage.h" #include "icsneo/communication/message/transmitmessage.h" #ifdef _MSC_VER @@ -923,6 +924,36 @@ std::shared_ptr Device::getHardwareInfo(std::chrono::milliseconds return hardwareInfo; } +std::shared_ptr Device::getMfgConfig() { + if(!isOpen()) { + report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error); + return nullptr; + } + + std::vector payload = MfgConfigMessage::EncodeArgumentsForGet(); + + auto response = com->waitForMessageSync( + [this, payload]() { + return com->sendCommand(ExtendedCommand::ProtobufAPI, payload); + }, + std::make_shared(Message::Type::MfgConfig), + std::chrono::milliseconds(250) + ); + + if(!response) { + report(APIEvent::Type::Timeout, APIEvent::Severity::Error); + return nullptr; + } + + auto mfgConfig = std::dynamic_pointer_cast(response); + if(!mfgConfig) { + report(APIEvent::Type::UnexpectedResponse, APIEvent::Severity::Error); + return nullptr; + } + + return mfgConfig; +} + std::optional Device::readLogicalDisk(uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout, Disk::MemoryType memType) { if(!into || timeout <= std::chrono::milliseconds(0)) { diff --git a/include/icsneo/communication/icspb.h b/include/icsneo/communication/icspb.h index bd14acd..9b99e43 100644 --- a/include/icsneo/communication/icspb.h +++ b/include/icsneo/communication/icspb.h @@ -9,6 +9,7 @@ #include #include #include +#include #ifdef _WIN32 #pragma warning(pop) #endif @@ -36,6 +37,11 @@ struct IDLookup { constexpr static common::v1::ProtoId value = common::v1::ProtoId::PROTO_ID_UNSPECIFIED; }; +template <> +struct IDLookup { + constexpr static common::v1::ProtoId value = common::v1::ProtoId::PROTO_ID_MFG_CONFIG; +}; + template <> struct IDLookup { constexpr static common::v1::ProtoId value = common::v1::ProtoId::PROTO_ID_NETWORK_MUTEX; diff --git a/include/icsneo/communication/message/message.h b/include/icsneo/communication/message/message.h index f323548..51ef82b 100644 --- a/include/icsneo/communication/message/message.h +++ b/include/icsneo/communication/message/message.h @@ -51,6 +51,7 @@ public: SPIPortKeyOperation = 0x8019, GenericAPIData = 0x8020, GenericAPIStatus = 0x8021, + MfgConfig = 0x8022, }; Message(Type t) : type(t) {} diff --git a/include/icsneo/communication/message/mfgconfigmessage.h b/include/icsneo/communication/message/mfgconfigmessage.h new file mode 100644 index 0000000..027ee2d --- /dev/null +++ b/include/icsneo/communication/message/mfgconfigmessage.h @@ -0,0 +1,56 @@ +#ifndef __MFGCONFIGMESSAGE_H_ +#define __MFGCONFIGMESSAGE_H_ + +#ifdef __cplusplus + +#include "icsneo/communication/message/message.h" +#include "icsneo/communication/message/allmacaddressesmessage.h" +#include "icsneo/device/chipid.h" + +#include +#include +#include +#include +#include + +namespace icsneo { + +class MfgConfigMessage : public Message { +public: + struct MfgDate { + uint32_t day = 0; + uint32_t month = 0; + uint32_t year = 0; + }; + + struct VersionNumber { + uint32_t major = 0; + uint32_t minor = 0; + std::optional release; + std::optional build; + }; + + MfgConfigMessage() : Message(Message::Type::MfgConfig) {} + + static std::shared_ptr DecodeToMessage(const std::vector& bytestream); + static std::vector EncodeArgumentsForGet(); + + std::optional serialNumber; + std::optional manufactureDate; + std::optional hardwareRev; + std::optional productId; + std::optional bootloaderRev; + std::optional usbDescriptor; + std::vector macAddresses; + std::optional pcbSerial; + std::optional chipId; + std::optional imei; + std::optional parentProductId; + std::optional softwareVersionLock; +}; + +} // namespace icsneo + +#endif // __cplusplus + +#endif // __MFGCONFIGMESSAGE_H_ diff --git a/include/icsneo/device/device.h b/include/icsneo/device/device.h index 457d557..cf0fa40 100644 --- a/include/icsneo/device/device.h +++ b/include/icsneo/device/device.h @@ -63,6 +63,7 @@ #include "icsneo/communication/message/gptpstatusmessage.h" #include "icsneo/communication/message/networkmutexmessage.h" #include "icsneo/communication/message/allmacaddressesmessage.h" +#include "icsneo/communication/message/mfgconfigmessage.h" #define ICSNEO_FINDABLE_DEVICE_BASE(className, type) \ static constexpr DeviceType::Enum DEVICE_TYPE = type; \ @@ -345,6 +346,7 @@ public: virtual Network getNetworkByNumber(Network::Type, size_t) const; std::shared_ptr getHardwareInfo(std::chrono::milliseconds timeout = std::chrono::milliseconds(100)); + std::shared_ptr getMfgConfig(); /**