// SPDX-License-Identifier: MIT /** Copyright (c) 2015 - 2022 Beckhoff Automation GmbH & Co. KG */ #pragma once #define UNUSED(x) (void)(x) #include "AdsDef.h" #include "wrap_endian.h" #include #include #include #pragma pack (push, 1) namespace Beckhoff { namespace Ads { struct AmsTcpHeader { AmsTcpHeader(const uint8_t* frame) { memcpy(this, frame, sizeof(*this)); } AmsTcpHeader(const uint32_t numBytes = 0) : reserved(0), leLength(Beckhoff::htole(numBytes)) { UNUSED(reserved); } uint32_t length() const { return Beckhoff::letoh(leLength); } private: uint16_t reserved; uint32_t leLength; }; struct AoERequestHeader { static const uint32_t SDO_UPLOAD = 0xF302; AoERequestHeader(uint16_t sdoIndex, uint8_t sdoSubIndex, uint32_t dataLength) : AoERequestHeader(SDO_UPLOAD, ((uint32_t)sdoIndex) << 16 | sdoSubIndex, dataLength) {} AoERequestHeader(uint32_t indexGroup, uint32_t indexOffset, uint32_t dataLength) : leGroup(Beckhoff::htole(indexGroup)), leOffset(Beckhoff::htole(indexOffset)), leLength(Beckhoff::htole(dataLength)) {} private: const uint32_t leGroup; const uint32_t leOffset; const uint32_t leLength; }; struct AoEReadWriteReqHeader : AoERequestHeader { AoEReadWriteReqHeader(uint32_t indexGroup, uint32_t indexOffset, uint32_t readLength, uint32_t writeLength) : AoERequestHeader(indexGroup, indexOffset, readLength), leWriteLength(Beckhoff::htole(writeLength)) {} private: const uint32_t leWriteLength; }; struct AdsWriteCtrlRequest { AdsWriteCtrlRequest(uint16_t ads, uint16_t dev, uint32_t dataLength) : leAdsState(Beckhoff::htole(ads)), leDevState(Beckhoff::htole(dev)), leLength(Beckhoff::htole(dataLength)) {} private: const uint16_t leAdsState; const uint16_t leDevState; const uint32_t leLength; }; struct AdsAddDeviceNotificationRequest { AdsAddDeviceNotificationRequest(uint32_t __group, uint32_t __offset, uint32_t __length, uint32_t __mode, uint32_t __maxDelay, uint32_t __cycleTime) : leGroup(Beckhoff::htole(__group)), leOffset(Beckhoff::htole(__offset)), leLength(Beckhoff::htole(__length)), leMode(Beckhoff::htole(__mode)), leMaxDelay(Beckhoff::htole(__maxDelay)), leCycleTime(Beckhoff::htole(__cycleTime)), reserved() { UNUSED(reserved); } private: const uint32_t leGroup; const uint32_t leOffset; const uint32_t leLength; const uint32_t leMode; const uint32_t leMaxDelay; const uint32_t leCycleTime; const std::array reserved; }; struct AoEHeader { static const uint16_t AMS_REQUEST = 0x0004; static const uint16_t AMS_RESPONSE = 0x0005; static const uint16_t AMS_UDP = 0x0040; static const uint16_t INVALID = 0x0000; static const uint16_t READ_DEVICE_INFO = 0x0001; static const uint16_t READ = 0x0002; static const uint16_t WRITE = 0x0003; static const uint16_t READ_STATE = 0x0004; static const uint16_t WRITE_CONTROL = 0x0005; static const uint16_t ADD_DEVICE_NOTIFICATION = 0x0006; static const uint16_t DEL_DEVICE_NOTIFICATION = 0x0007; static const uint16_t DEVICE_NOTIFICATION = 0x0008; static const uint16_t READ_WRITE = 0x0009; AoEHeader() : leTargetPort(0), leSourcePort(0), leCmdId(0), leStateFlags(0), leLength(0), leErrorCode(0), leInvokeId(0) {} AoEHeader(const AmsNetId& __targetAddr, uint16_t __targetPort, const AmsNetId& __sourceAddr, uint16_t __sourcePort, uint16_t __cmdId, uint32_t __length, uint32_t __invokeId) : targetNetId(__targetAddr), leTargetPort(Beckhoff::htole(__targetPort)), sourceNetId(__sourceAddr), leSourcePort(Beckhoff::htole(__sourcePort)), leCmdId(Beckhoff::htole(__cmdId)), leStateFlags(Beckhoff::htole(AMS_REQUEST)), leLength(Beckhoff::htole(__length)), leErrorCode(0), leInvokeId(Beckhoff::htole(__invokeId)) {} AoEHeader(const uint8_t* frame) { memcpy(this, frame, sizeof(*this)); } uint16_t cmdId() const { return Beckhoff::letoh(leCmdId); } uint32_t errorCode() const { return Beckhoff::letoh(leErrorCode); } uint32_t invokeId() const { return Beckhoff::letoh(leInvokeId); } uint32_t length() const { return Beckhoff::letoh(leLength); } AmsAddr sourceAms() const { return AmsAddr { sourceAddr(), sourcePort() }; } AmsNetId sourceAddr() const { return sourceNetId; } uint16_t sourcePort() const { return Beckhoff::letoh(leSourcePort); } uint16_t stateFlags() const { return Beckhoff::letoh(leStateFlags); } AmsNetId targetAddr() const { return targetNetId; } uint16_t targetPort() const { return Beckhoff::letoh(leTargetPort); } private: AmsNetId targetNetId; uint16_t leTargetPort; AmsNetId sourceNetId; uint16_t leSourcePort; uint16_t leCmdId; uint16_t leStateFlags; uint32_t leLength; uint32_t leErrorCode; uint32_t leInvokeId; }; struct AoEResponseHeader { AoEResponseHeader() : leResult(0) {} AoEResponseHeader(const uint8_t* frame) { memcpy(this, frame, sizeof(*this)); } uint32_t result() const { return Beckhoff::letoh(leResult); } private: uint32_t leResult; }; struct AoEReadResponseHeader : AoEResponseHeader { AoEReadResponseHeader() : leReadLength(0) {} AoEReadResponseHeader(const uint8_t* frame) { memcpy(this, frame, sizeof(*this)); } uint32_t readLength() const { return Beckhoff::letoh(leReadLength); } private: uint32_t leReadLength; }; } } #pragma pack (pop)