map/das-dn/third_party/AdsLib/Standalone/AdsLib.cpp

324 lines
9.5 KiB
C++
Raw Normal View History

2024-12-03 10:36:06 +08:00
// SPDX-License-Identifier: MIT
/**
Copyright (c) 2015 - 2022 Beckhoff Automation GmbH & Co. KG
*/
#include "AdsLib.h"
#include "AmsRouter.h"
2024-12-09 09:41:04 +08:00
#include <iostream>
2024-12-03 10:36:06 +08:00
2024-12-09 09:41:04 +08:00
namespace Beckhoff
{
namespace Ads
{
static AmsRouter& GetLocalAmsRouter()
2024-12-03 10:36:06 +08:00
{
static AmsRouter router;
return router;
}
#define ASSERT_PORT(port) do { \
if ((port) <= 0 || (port) > UINT16_MAX) { \
return ADSERR_CLIENT_PORTNOTOPEN; \
} \
} while (false)
#define ASSERT_PORT_AND_AMSADDR(port, pAddr) do { \
ASSERT_PORT(port); \
if (!(pAddr)) { \
return ADSERR_CLIENT_NOAMSADDR; \
} \
} while (false)
2024-12-09 09:41:04 +08:00
long ConnectTarget(const AmsNetId ams, const char* ip)
2024-12-03 10:36:06 +08:00
{
try {
2024-12-09 09:41:04 +08:00
return GetLocalAmsRouter().ConnectTarget(ams, ip);
2024-12-03 10:36:06 +08:00
} catch (const std::bad_alloc&) {
return GLOBALERR_NO_MEMORY;
} catch (const std::runtime_error&) {
return GLOBALERR_TARGET_PORT;
}
}
2024-12-09 09:41:04 +08:00
void DisconnectTarget(const AmsNetId ams)
2024-12-03 10:36:06 +08:00
{
2024-12-09 09:41:04 +08:00
GetLocalAmsRouter().DisconnectTarget(ams);
2024-12-03 10:36:06 +08:00
}
2024-12-09 09:41:04 +08:00
void SetLocalAmsNetId(const AmsNetId ams)
2024-12-03 10:36:06 +08:00
{
2024-12-09 09:41:04 +08:00
GetLocalAmsRouter().SetAmsNetId(ams);
2024-12-03 10:36:06 +08:00
}
2024-12-09 09:41:04 +08:00
long CloseLocalPort(long localPort)
2024-12-03 10:36:06 +08:00
{
2024-12-09 09:41:04 +08:00
ASSERT_PORT(localPort);
return GetLocalAmsRouter().ClosePort((uint16_t)localPort);
2024-12-03 10:36:06 +08:00
}
2024-12-09 09:41:04 +08:00
long OpenLocalPort()
2024-12-03 10:36:06 +08:00
{
2024-12-09 09:41:04 +08:00
return GetLocalAmsRouter().OpenPort();
2024-12-03 10:36:06 +08:00
}
2024-12-09 09:41:04 +08:00
long GetLocalAmsAddr(long localPort, AmsAddr* pAddr)
2024-12-03 10:36:06 +08:00
{
2024-12-09 09:41:04 +08:00
ASSERT_PORT_AND_AMSADDR(localPort, pAddr);
return GetLocalAmsRouter().GetAmsAddr((uint16_t)localPort, pAddr);
2024-12-03 10:36:06 +08:00
}
2024-12-09 09:41:04 +08:00
long AdsSyncReadReqEx2(long localPort,
2024-12-03 10:36:06 +08:00
const AmsAddr* pAddr,
uint32_t indexGroup,
uint32_t indexOffset,
uint32_t bufferLength,
void* buffer,
uint32_t* bytesRead)
{
2024-12-09 09:41:04 +08:00
ASSERT_PORT_AND_AMSADDR(localPort, pAddr);
2024-12-03 10:36:06 +08:00
if (!buffer) {
return ADSERR_CLIENT_INVALIDPARM;
}
try {
AmsRequest request {
*pAddr,
2024-12-09 09:41:04 +08:00
(uint16_t)localPort,
2024-12-03 10:36:06 +08:00
AoEHeader::READ,
bufferLength,
buffer,
bytesRead,
sizeof(AoERequestHeader)
};
request.frame.prepend(AoERequestHeader {
indexGroup,
indexOffset,
bufferLength
});
2024-12-09 09:41:04 +08:00
return GetLocalAmsRouter().SendAdsRequest(request);
2024-12-03 10:36:06 +08:00
} catch (const std::bad_alloc&) {
return GLOBALERR_NO_MEMORY;
}
}
2024-12-09 09:41:04 +08:00
long AdsSyncReadDeviceInfoReqEx(long localPort, const AmsAddr* pAddr, char* devName, AdsVersion* version)
2024-12-03 10:36:06 +08:00
{
2024-12-09 09:41:04 +08:00
ASSERT_PORT_AND_AMSADDR(localPort, pAddr);
2024-12-03 10:36:06 +08:00
if (!devName || !version) {
return ADSERR_CLIENT_INVALIDPARM;
}
try {
static const size_t NAME_LENGTH = 16;
uint8_t buffer[sizeof(*version) + NAME_LENGTH];
AmsRequest request {
*pAddr,
2024-12-09 09:41:04 +08:00
(uint16_t)localPort,
2024-12-03 10:36:06 +08:00
AoEHeader::READ_DEVICE_INFO,
sizeof(buffer),
buffer
};
2024-12-09 09:41:04 +08:00
const auto status = GetLocalAmsRouter().SendAdsRequest(request);
2024-12-03 10:36:06 +08:00
if (!status) {
version->version = buffer[0];
version->revision = buffer[1];
2024-12-09 09:41:04 +08:00
version->build = Beckhoff::letoh<uint16_t>(buffer + offsetof(AdsVersion, build));
2024-12-03 10:36:06 +08:00
memcpy(devName, buffer + sizeof(*version), NAME_LENGTH);
}
return status;
} catch (const std::bad_alloc&) {
return GLOBALERR_NO_MEMORY;
}
}
2024-12-09 09:41:04 +08:00
long AdsSyncReadStateReqEx(long localPort, const AmsAddr* pAddr, uint16_t* adsState, uint16_t* devState)
2024-12-03 10:36:06 +08:00
{
2024-12-09 09:41:04 +08:00
ASSERT_PORT_AND_AMSADDR(localPort, pAddr);
2024-12-03 10:36:06 +08:00
if (!adsState || !devState) {
return ADSERR_CLIENT_INVALIDPARM;
}
try {
uint16_t buffer[2];
AmsRequest request {
*pAddr,
2024-12-09 09:41:04 +08:00
(uint16_t)localPort,
2024-12-03 10:36:06 +08:00
AoEHeader::READ_STATE,
sizeof(buffer),
buffer
};
2024-12-09 09:41:04 +08:00
const auto status = GetLocalAmsRouter().SendAdsRequest(request);
2024-12-03 10:36:06 +08:00
if (!status) {
2024-12-09 09:41:04 +08:00
*adsState = Beckhoff::letoh(buffer[0]);
*devState = Beckhoff::letoh(buffer[1]);
2024-12-03 10:36:06 +08:00
}
return status;
} catch (const std::bad_alloc&) {
return GLOBALERR_NO_MEMORY;
}
}
2024-12-09 09:41:04 +08:00
long AdsSyncReadWriteReqEx2(long localPort,
2024-12-03 10:36:06 +08:00
const AmsAddr* pAddr,
uint32_t indexGroup,
uint32_t indexOffset,
uint32_t readLength,
void* readData,
uint32_t writeLength,
const void* writeData,
uint32_t* bytesRead)
{
2024-12-09 09:41:04 +08:00
ASSERT_PORT_AND_AMSADDR(localPort, pAddr);
2024-12-03 10:36:06 +08:00
if ((readLength && !readData) || (writeLength && !writeData)) {
return ADSERR_CLIENT_INVALIDPARM;
}
try {
AmsRequest request {
*pAddr,
2024-12-09 09:41:04 +08:00
(uint16_t)localPort,
2024-12-03 10:36:06 +08:00
AoEHeader::READ_WRITE,
readLength,
readData,
bytesRead,
sizeof(AoEReadWriteReqHeader) + writeLength
};
request.frame.prepend(writeData, writeLength);
request.frame.prepend(AoEReadWriteReqHeader {
indexGroup,
indexOffset,
readLength,
writeLength
});
2024-12-09 09:41:04 +08:00
return GetLocalAmsRouter().SendAdsRequest(request);
2024-12-03 10:36:06 +08:00
} catch (const std::bad_alloc&) {
return GLOBALERR_NO_MEMORY;
}
}
2024-12-09 09:41:04 +08:00
long AdsSyncWriteReqEx(long localPort,
2024-12-03 10:36:06 +08:00
const AmsAddr* pAddr,
uint32_t indexGroup,
uint32_t indexOffset,
uint32_t bufferLength,
const void* buffer)
{
2024-12-09 09:41:04 +08:00
ASSERT_PORT_AND_AMSADDR(localPort, pAddr);
2024-12-03 10:36:06 +08:00
if (!buffer) {
return ADSERR_CLIENT_INVALIDPARM;
}
try {
AmsRequest request {
*pAddr,
2024-12-09 09:41:04 +08:00
(uint16_t)localPort,
2024-12-03 10:36:06 +08:00
AoEHeader::WRITE,
0, nullptr, nullptr,
sizeof(AoERequestHeader) + bufferLength,
};
request.frame.prepend(buffer, bufferLength);
request.frame.prepend<AoERequestHeader>({
indexGroup,
indexOffset,
bufferLength
});
2024-12-09 09:41:04 +08:00
return GetLocalAmsRouter().SendAdsRequest(request);
2024-12-03 10:36:06 +08:00
} catch (const std::bad_alloc&) {
return GLOBALERR_NO_MEMORY;
}
}
2024-12-09 09:41:04 +08:00
long AdsSyncWriteControlReqEx(long localPort,
2024-12-03 10:36:06 +08:00
const AmsAddr* pAddr,
uint16_t adsState,
uint16_t devState,
uint32_t bufferLength,
const void* buffer)
{
2024-12-09 09:41:04 +08:00
ASSERT_PORT_AND_AMSADDR(localPort, pAddr);
2024-12-03 10:36:06 +08:00
try {
AmsRequest request {
*pAddr,
2024-12-09 09:41:04 +08:00
(uint16_t)localPort,
2024-12-03 10:36:06 +08:00
AoEHeader::WRITE_CONTROL,
0, nullptr, nullptr,
sizeof(AdsWriteCtrlRequest) + bufferLength
};
request.frame.prepend(buffer, bufferLength);
request.frame.prepend<AdsWriteCtrlRequest>({
adsState,
devState,
bufferLength
});
2024-12-09 09:41:04 +08:00
return GetLocalAmsRouter().SendAdsRequest(request);
2024-12-03 10:36:06 +08:00
} catch (const std::bad_alloc&) {
return GLOBALERR_NO_MEMORY;
}
}
2024-12-09 09:41:04 +08:00
long AdsSyncAddDeviceNotificationReqEx(long localPort,
2024-12-03 10:36:06 +08:00
const AmsAddr* pAddr,
uint32_t indexGroup,
uint32_t indexOffset,
const AdsNotificationAttrib* pAttrib,
PAdsNotificationFuncEx pFunc,
uint32_t hUser,
uint32_t* pNotification)
{
2024-12-09 09:41:04 +08:00
ASSERT_PORT_AND_AMSADDR(localPort, pAddr);
2024-12-03 10:36:06 +08:00
if (!pAttrib || !pFunc || !pNotification) {
return ADSERR_CLIENT_INVALIDPARM;
}
try {
uint8_t buffer[sizeof(*pNotification)];
AmsRequest request {
*pAddr,
2024-12-09 09:41:04 +08:00
(uint16_t)localPort,
2024-12-03 10:36:06 +08:00
AoEHeader::ADD_DEVICE_NOTIFICATION,
sizeof(buffer),
buffer,
nullptr,
sizeof(AdsAddDeviceNotificationRequest)
};
request.frame.prepend(AdsAddDeviceNotificationRequest {
indexGroup,
indexOffset,
pAttrib->cbLength,
pAttrib->nTransMode,
pAttrib->nMaxDelay,
pAttrib->nCycleTime
});
2024-12-09 09:41:04 +08:00
auto notify = std::make_shared<Notification>(pFunc, hUser, pAttrib->cbLength, *pAddr, (uint16_t)localPort);
return GetLocalAmsRouter().AddNotification(
2024-12-03 10:36:06 +08:00
request,
pNotification,
notify);
} catch (const std::bad_alloc&) {
return GLOBALERR_NO_MEMORY;
}
}
2024-12-09 09:41:04 +08:00
long AdsSyncDelDeviceNotificationReqEx(long localPort, const AmsAddr* pAddr, uint32_t hNotification)
2024-12-03 10:36:06 +08:00
{
2024-12-09 09:41:04 +08:00
ASSERT_PORT_AND_AMSADDR(localPort, pAddr);
return GetLocalAmsRouter().DelNotification((uint16_t)localPort, pAddr, hNotification);
2024-12-03 10:36:06 +08:00
}
2024-12-09 09:41:04 +08:00
long AdsSyncGetTimeoutEx(long localPort, uint32_t* timeout)
2024-12-03 10:36:06 +08:00
{
2024-12-09 09:41:04 +08:00
ASSERT_PORT(localPort);
2024-12-03 10:36:06 +08:00
if (!timeout) {
return ADSERR_CLIENT_INVALIDPARM;
}
2024-12-09 09:41:04 +08:00
return GetLocalAmsRouter().GetTimeout((uint16_t)localPort, *timeout);
2024-12-03 10:36:06 +08:00
}
2024-12-09 09:41:04 +08:00
long AdsSyncSetTimeoutEx(long localPort, uint32_t timeout)
2024-12-03 10:36:06 +08:00
{
2024-12-09 09:41:04 +08:00
ASSERT_PORT(localPort);
return GetLocalAmsRouter().SetTimeout((uint16_t)localPort, timeout);
}
2024-12-03 10:36:06 +08:00
}
2024-12-09 09:41:04 +08:00
}