diff --git a/communication/packet/componentversionpacket.cpp b/communication/packet/componentversionpacket.cpp index ab29985..ec9a1ed 100644 --- a/communication/packet/componentversionpacket.cpp +++ b/communication/packet/componentversionpacket.cpp @@ -31,7 +31,7 @@ std::shared_ptr ComponentVersionPacket::DecodeToMessag // Get a reference to the payload to fully validate the length const auto& response = *reinterpret_cast(bytes.data()); // Expected size is the header, numVersions field, and numVersions ComponentVersion objects. - auto expectedSize = sizeof(ExtendedResponseMessage::ResponseHeader) + 2 + (response.numVersions * sizeof(ComponentVersion)); + auto expectedSize = sizeof(ExtendedResponseMessage::ResponseHeader) + 2 + (response.numVersions * sizeof(PackedComponentVersion)); // If the response is malformed (too small), return an empty message. if(bytes.size() < expectedSize) { return msg; // Empty @@ -39,7 +39,14 @@ std::shared_ptr ComponentVersionPacket::DecodeToMessag // Unpack into the portable class for(unsigned int i = 0; i < response.numVersions; ++i) { const auto& packedVersion = response.versions[i]; - msg->versions.emplace_back(packedVersion.valid, packedVersion.componentInfo, packedVersion.identifier, packedVersion.dotVersion, packedVersion.commitHash); + msg->versions.emplace_back( + packedVersion.valid, + packedVersion.componentInfo, + packedVersion.identifier, + packedVersion.dotVersion, + packedVersion.commitHash, + packedVersion.expansionSlot + ); } return msg; } diff --git a/device/device.cpp b/device/device.cpp index 063db18..d3528c5 100644 --- a/device/device.cpp +++ b/device/device.cpp @@ -134,6 +134,18 @@ std::pair>, bool> Device::getMessages() { return std::make_pair(ret, retBool); } +std::shared_ptr Device::getExtension(const std::string& name) const { + std::shared_ptr ret; + std::lock_guard lk(extensionsLock); + for(auto& ext : extensions) { + if((ext->getName() == name)) { + ret = ext; + break; + } + } + return ret; +} + bool Device::getMessages(std::vector>& container, size_t limit, std::chrono::milliseconds timeout) { if(!isOpen()) { report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error); @@ -180,6 +192,14 @@ void Device::enforcePollingMessageLimit() { } } +bool Device::refreshComponentVersions() { + if(auto compVersions = com->getComponentVersionsSync()) { + componentVersions = std::move(*compVersions); + return true; + } + return false; +} + bool Device::open(OpenFlags flags, OpenStatusHandler handler) { if(!com) { report(APIEvent::Type::Unknown, APIEvent::Severity::Error); @@ -199,6 +219,7 @@ bool Device::open(OpenFlags flags, OpenStatusHandler handler) { tryAgain = true; return true; }); + if(!tryAgain) { com->close(); report(attemptErr, APIEvent::Severity::Error); @@ -222,15 +243,7 @@ bool Device::open(OpenFlags flags, OpenStatusHandler handler) { if(block) // Extensions say no return false; - // Get component versions again *after* the extension "onDeviceOpen" hooks (e.g. device reflashes) - if(supportsComponentVersions()) { - if(auto compVersions = com->getComponentVersionsSync()) - componentVersions = std::move(*compVersions); - else - // It's possible the device is on older firmware so don't return false here - report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::EventWarning); - } - + refreshComponentVersions(); if(!settings->disabled) { // Since we will not fail the open if a settings read fails, // downgrade any errors to warnings. Otherwise the error will @@ -336,13 +349,14 @@ APIEvent::Type Device::attemptToBeginCommunication() { return getCommunicationNotEstablishedError(); std::this_thread::sleep_for(std::chrono::milliseconds(10)); - auto serial = com->getSerialNumberSync(); + auto serial = com->getSerialNumberSync(std::chrono::milliseconds(200)); int i = 0; while(!serial) { - serial = com->getSerialNumberSync(); + serial = com->getSerialNumberSync(std::chrono::milliseconds(200)); if(i++ > 5) break; } + if(!serial) // "Communication could not be established with the device. Perhaps it is not powered with 12 volts?" return getCommunicationNotEstablishedError(); @@ -356,7 +370,6 @@ APIEvent::Type Device::attemptToBeginCommunication() { else versions = std::move(*maybeVersions); - // Get component versions before the extension "onDeviceOpen" hooks so that we can properly check verisons if(supportsComponentVersions()) { if(auto compVersions = com->getComponentVersionsSync()) diff --git a/include/icsneo/communication/message/componentversionsmessage.h b/include/icsneo/communication/message/componentversionsmessage.h index 0a7c245..ae4c210 100644 --- a/include/icsneo/communication/message/componentversionsmessage.h +++ b/include/icsneo/communication/message/componentversionsmessage.h @@ -7,8 +7,8 @@ namespace icsneo { class ComponentVersion { public: - ComponentVersion(uint8_t valid, uint8_t componentInfo, uint32_t identifier, uint32_t dotVersion, uint32_t commitHash) : - valid(valid), componentInfo(componentInfo), identifier(identifier), dotVersion(dotVersion), commitHash(commitHash) {} + ComponentVersion(uint8_t valid, uint8_t componentInfo, uint32_t identifier, uint32_t dotVersion, uint32_t commitHash, uint8_t expansionSlot) : + valid(valid), componentInfo(componentInfo), identifier(identifier), dotVersion(dotVersion), commitHash(commitHash), expansionSlot(expansionSlot) {} static ComponentVersion FromAppVersion(uint32_t identifier, uint8_t appMajor, uint8_t appMinor) { uint32_t dotVersion = (appMajor << 24) | (appMinor << 16); @@ -19,6 +19,7 @@ public: static_cast(0u), identifier, dotVersion, + static_cast(0u), static_cast(0u) ); } @@ -28,6 +29,7 @@ public: const uint32_t identifier; const uint32_t dotVersion; const uint32_t commitHash; + const uint8_t expansionSlot; }; class ComponentVersionsMessage : public Message { diff --git a/include/icsneo/communication/message/filter/extendedresponsefilter.h b/include/icsneo/communication/message/filter/extendedresponsefilter.h new file mode 100644 index 0000000..4ae8741 --- /dev/null +++ b/include/icsneo/communication/message/filter/extendedresponsefilter.h @@ -0,0 +1,39 @@ +#ifndef __EXTENDEDRESPONSEFILTER_H_ +#define __EXTENDEDRESPONSEFILTER_H_ + +#ifdef __cplusplus + +#include "icsneo/communication/message/filter/messagefilter.h" +#include "icsneo/communication/network.h" +#include "icsneo/communication/communication.h" +#include "icsneo/communication/command.h" +#include "icsneo/communication/message/extendedresponsemessage.h" +#include +#include + +namespace icsneo { + +class ExtendedResponseFilter : public MessageFilter { +public: + ExtendedResponseFilter(icsneo::ExtendedResponse resp) : MessageFilter(Message::Type::ExtendedResponse), response(resp) {} + + bool match(const std::shared_ptr& message) const override { + if(!MessageFilter::match(message)) { + return false; + } + const auto respMsg = std::static_pointer_cast(message); + return respMsg && matchResponse(respMsg->response); + } + +private: + icsneo::ExtendedResponse response; + bool matchResponse(icsneo::ExtendedResponse resp) const { + return response == resp; + } +}; + +} + +#endif // __cplusplus + +#endif \ No newline at end of file diff --git a/include/icsneo/device/device.h b/include/icsneo/device/device.h index e940de8..f393e56 100644 --- a/include/icsneo/device/device.h +++ b/include/icsneo/device/device.h @@ -570,6 +570,7 @@ public: NODISCARD("If the Lifetime is not held, disconnects will be immediately unsuppressed") Lifetime suppressDisconnects(); + bool refreshComponentVersions(); /** * For use by extensions only. A more stable API will be provided in the future. */ @@ -727,7 +728,9 @@ public: virtual bool isOnlineSupported() const { return true; } - virtual bool supportsComponentVersions() const { return false; } + virtual bool supportsComponentVersions() const { + return !getComponentVersions().empty(); + } virtual bool supportsTC10() const { return false; } @@ -743,6 +746,8 @@ public: /* MACsec support */ virtual bool writeMACsecConfig(const MACsecMessage& message, uint16_t binaryIndex); + std::shared_ptr getExtension(const std::string& name) const; + protected: bool online = false; int messagePollingCallbackID = 0; @@ -824,12 +829,6 @@ protected: virtual void setupExtensions() {} - // Hook for devices such as FIRE which need to inject traffic before RequestSerialNumber - // Return false to bail - virtual bool afterCommunicationOpen() { return true; } - - virtual bool requiresVehiclePower() const { return true; } - template std::shared_ptr getExtension() const { std::shared_ptr ret; @@ -841,6 +840,12 @@ protected: return ret; } // END Initialization Functions + // Hook for devices such as FIRE which need to inject traffic before RequestSerialNumber + // Return false to bail + virtual bool afterCommunicationOpen() { return true; } + + virtual bool requiresVehiclePower() const { return true; } + void handleInternalMessage(std::shared_ptr message); diff --git a/include/icsneo/device/extensions/deviceextension.h b/include/icsneo/device/extensions/deviceextension.h index b45596f..59dfe3e 100644 --- a/include/icsneo/device/extensions/deviceextension.h +++ b/include/icsneo/device/extensions/deviceextension.h @@ -28,6 +28,7 @@ public: virtual void onGoOffline() {} virtual void onDeviceClose() {} + virtual void setGenericData(void*) {} virtual bool providesFirmware() const { return false; } virtual void handleMessage(const std::shared_ptr&) {} diff --git a/include/icsneo/device/tree/etherbadge/etherbadge.h b/include/icsneo/device/tree/etherbadge/etherbadge.h index 96254ca..47c9de4 100644 --- a/include/icsneo/device/tree/etherbadge/etherbadge.h +++ b/include/icsneo/device/tree/etherbadge/etherbadge.h @@ -26,8 +26,6 @@ public: return supportedNetworks; } - bool supportsComponentVersions() const override { return true; } - protected: EtherBADGE(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) { initialize(makeDriver); diff --git a/include/icsneo/device/tree/neoviconnect/neoviconnect.h b/include/icsneo/device/tree/neoviconnect/neoviconnect.h index cadda34..9dc012b 100644 --- a/include/icsneo/device/tree/neoviconnect/neoviconnect.h +++ b/include/icsneo/device/tree/neoviconnect/neoviconnect.h @@ -69,7 +69,6 @@ protected: return 0; } - bool supportsComponentVersions() const override { return true; } bool supportsGPTP() const override { return true; } }; diff --git a/include/icsneo/device/tree/neovifire2/neovifire2.h b/include/icsneo/device/tree/neovifire2/neovifire2.h index 2392aea..2cb83b5 100644 --- a/include/icsneo/device/tree/neovifire2/neovifire2.h +++ b/include/icsneo/device/tree/neovifire2/neovifire2.h @@ -87,8 +87,6 @@ public: }; } - bool supportsComponentVersions() const override { return true; } - protected: NeoVIFIRE2(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) { initialize(makeDriver); diff --git a/include/icsneo/device/tree/neovifire3/neovifire3.h b/include/icsneo/device/tree/neovifire3/neovifire3.h index 4842920..4b72577 100644 --- a/include/icsneo/device/tree/neovifire3/neovifire3.h +++ b/include/icsneo/device/tree/neovifire3/neovifire3.h @@ -49,9 +49,6 @@ public: }; return supportedNetworks; } - - bool supportsComponentVersions() const override { return true; } - protected: NeoVIFIRE3(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) { initialize(makeDriver); diff --git a/include/icsneo/device/tree/neovifire3flexray/neovifire3flexray.h b/include/icsneo/device/tree/neovifire3flexray/neovifire3flexray.h index 2aaf196..05edc31 100644 --- a/include/icsneo/device/tree/neovifire3flexray/neovifire3flexray.h +++ b/include/icsneo/device/tree/neovifire3flexray/neovifire3flexray.h @@ -52,8 +52,6 @@ public: return supportedNetworks; } - bool supportsComponentVersions() const override { return true; } - protected: NeoVIFIRE3FlexRay(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) { initialize(makeDriver); diff --git a/include/icsneo/device/tree/neovired2/neovired2.h b/include/icsneo/device/tree/neovired2/neovired2.h index cd53f8e..d8070c7 100644 --- a/include/icsneo/device/tree/neovired2/neovired2.h +++ b/include/icsneo/device/tree/neovired2/neovired2.h @@ -35,7 +35,6 @@ public: return supportedNetworks; } - bool supportsComponentVersions() const override { return true; } bool supportsGPTP() const override { return true; } protected: diff --git a/include/icsneo/device/tree/plasion/neoviion.h b/include/icsneo/device/tree/plasion/neoviion.h index b1c2ccb..b3896f3 100644 --- a/include/icsneo/device/tree/plasion/neoviion.h +++ b/include/icsneo/device/tree/plasion/neoviion.h @@ -15,8 +15,6 @@ public: // USB PID is 0x0901, standard driver is FTDI ICSNEO_FINDABLE_DEVICE_BY_PID(NeoVIION, DeviceType::ION, 0x0901); - bool supportsComponentVersions() const override { return true; } - private: NeoVIION(neodevice_t neodevice, const driver_factory_t& makeDriver) : Plasion(neodevice) { initialize(makeDriver); diff --git a/include/icsneo/device/tree/radepsilon/radepsilon.h b/include/icsneo/device/tree/radepsilon/radepsilon.h index c666f9b..2731c4c 100644 --- a/include/icsneo/device/tree/radepsilon/radepsilon.h +++ b/include/icsneo/device/tree/radepsilon/radepsilon.h @@ -25,8 +25,6 @@ public: return supportedNetworks; } - bool supportsComponentVersions() const override { return true; } - protected: RADEpsilon(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) { initialize(makeDriver); diff --git a/include/icsneo/device/tree/radjupiter/radjupiter.h b/include/icsneo/device/tree/radjupiter/radjupiter.h index f4e7c57..2e6160c 100644 --- a/include/icsneo/device/tree/radjupiter/radjupiter.h +++ b/include/icsneo/device/tree/radjupiter/radjupiter.h @@ -29,8 +29,6 @@ public: bool getEthPhyRegControlSupported() const override { return true; } - bool supportsComponentVersions() const override { return true; } - protected: RADJupiter(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) { initialize(makeDriver); diff --git a/include/icsneo/device/tree/radmoon2/radmoon2zl.h b/include/icsneo/device/tree/radmoon2/radmoon2zl.h index f441c70..27ae008 100644 --- a/include/icsneo/device/tree/radmoon2/radmoon2zl.h +++ b/include/icsneo/device/tree/radmoon2/radmoon2zl.h @@ -16,8 +16,6 @@ public: uint8_t getPhyAddrOrPort() const override { return 1; } - bool supportsComponentVersions() const override { return true; } - bool supportsTC10() const override { return true; } protected: diff --git a/include/icsneo/device/tree/radmoon3/radmoon3.h b/include/icsneo/device/tree/radmoon3/radmoon3.h index 0d714ae..f8f7422 100644 --- a/include/icsneo/device/tree/radmoon3/radmoon3.h +++ b/include/icsneo/device/tree/radmoon3/radmoon3.h @@ -28,8 +28,6 @@ public: bool isOnlineSupported() const override { return false; } - bool supportsComponentVersions() const override { return true; } - bool supportsTC10() const override { return true; } protected: diff --git a/include/icsneo/device/tree/radmoonduo/radmoonduo.h b/include/icsneo/device/tree/radmoonduo/radmoonduo.h index da82177..ec83366 100644 --- a/include/icsneo/device/tree/radmoonduo/radmoonduo.h +++ b/include/icsneo/device/tree/radmoonduo/radmoonduo.h @@ -25,8 +25,6 @@ public: bool getEthPhyRegControlSupported() const override { return true; } - bool supportsComponentVersions() const override { return true; } - protected: RADMoonDuo(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) { initialize(makeDriver); diff --git a/include/icsneo/device/tree/radpluto/radpluto.h b/include/icsneo/device/tree/radpluto/radpluto.h index a1fd358..66c16dc 100644 --- a/include/icsneo/device/tree/radpluto/radpluto.h +++ b/include/icsneo/device/tree/radpluto/radpluto.h @@ -34,8 +34,6 @@ public: bool getEthPhyRegControlSupported() const override { return true; } - bool supportsComponentVersions() const override { return true; } - protected: RADPluto(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) { initialize(makeDriver); diff --git a/include/icsneo/device/tree/valuecan3/valuecan3.h b/include/icsneo/device/tree/valuecan3/valuecan3.h index 1731019..4250cab 100644 --- a/include/icsneo/device/tree/valuecan3/valuecan3.h +++ b/include/icsneo/device/tree/valuecan3/valuecan3.h @@ -22,8 +22,6 @@ public: return supportedNetworks; } - bool supportsComponentVersions() const override { return true; } - private: ValueCAN3(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) { initialize(makeDriver); diff --git a/include/icsneo/device/tree/valuecan4/valuecan4.h b/include/icsneo/device/tree/valuecan4/valuecan4.h index 8addc3f..81ee7e0 100644 --- a/include/icsneo/device/tree/valuecan4/valuecan4.h +++ b/include/icsneo/device/tree/valuecan4/valuecan4.h @@ -11,9 +11,6 @@ namespace icsneo { class ValueCAN4 : public Device { public: // All ValueCAN 4 devices share a USB PID of 0x1101 - - bool supportsComponentVersions() const override { return true; } - protected: using Device::Device; diff --git a/include/icsneo/device/tree/vividcan/vividcan.h b/include/icsneo/device/tree/vividcan/vividcan.h index aedeefc..6bdd1ea 100644 --- a/include/icsneo/device/tree/vividcan/vividcan.h +++ b/include/icsneo/device/tree/vividcan/vividcan.h @@ -28,9 +28,6 @@ public: } bool isOnlineSupported() const override { return false; } - - bool supportsComponentVersions() const override { return true; } - protected: VividCAN(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) { initialize(makeDriver);