232 lines
7.7 KiB
C
232 lines
7.7 KiB
C
/*******************************************************************************
|
|
* Copyright (c) 2019, Rockwell Automation, Inc.
|
|
* All rights reserved.
|
|
*
|
|
******************************************************************************/
|
|
/** @file
|
|
* @brief Implements the DLR object
|
|
* @author Stefan Maetje <stefan.maetje@esd.eu>
|
|
*
|
|
* CIP DLR object
|
|
* ==============
|
|
*
|
|
* This module implements the DLR object for a non supervisor and non gateway
|
|
* device.
|
|
*
|
|
* Implemented Attributes
|
|
* ----------------------
|
|
* - Attribute 1: Network Topology
|
|
* - Attribute 2: Network Status
|
|
* - Attribute 10: Active Supervisor Address
|
|
* - Attribute 12: Capability Flags
|
|
*
|
|
* Non-implemented attributes
|
|
* --------------------------
|
|
* The attributes 3, 4, 5, 6, 7, 8, 9 and 11 are only required for devices
|
|
* that are capable of functioning as a ring supervisor. These attributes
|
|
* shall not be implemented by non-supervisor devices.
|
|
*
|
|
* The attributes 13, 14, 15 and 16 are only required for devices that are
|
|
* capable of functioning as a redundant gateway. These attributes shall
|
|
* not be implemented by non-redundant gateway devices.
|
|
*
|
|
* None of the attributes 17, 18 and 19 is required and implemented.
|
|
* Because of this the Object Revision stays on level 3 (see @ref
|
|
* DLR_CLASS_REVISION).
|
|
*
|
|
* Implemented Services
|
|
* --------------------
|
|
* - GetAttributesAll
|
|
* - GetAttributeSingle
|
|
*/
|
|
/* ********************************************************************
|
|
* include files
|
|
*/
|
|
#include "cipdlr.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include "cipcommon.h"
|
|
#include "opener_api.h"
|
|
#include "trace.h"
|
|
#include "endianconv.h"
|
|
|
|
/* ********************************************************************
|
|
* defines
|
|
*/
|
|
/** The implemented class revision is still 3 because the attributes
|
|
* mandatory for revision 4 are NOT implemented. */
|
|
#define DLR_CLASS_REVISION 3
|
|
|
|
/* ********************************************************************
|
|
* Type declarations
|
|
*/
|
|
|
|
/* ********************************************************************
|
|
* module local variables
|
|
*/
|
|
/* Define variables with default values to be used for the
|
|
* GetAttributeAll response for not implemented attributes. */
|
|
static const CipUsint s_0xFF_default = 0xFFU;
|
|
static const CipUint s_0xFFFF_default = 0xFFFFU;
|
|
|
|
static const CipUsint s_0x00_default = 0x00U;
|
|
static const CipUint s_0x0000_default = 0x0000U;
|
|
static const CipUdint s_0x00000000_default = 0x00000000U;
|
|
|
|
static const CipNodeAddress s_zero_node = {
|
|
.device_ip = 0,
|
|
.device_mac = {
|
|
0, 0, 0, 0, 0, 0,
|
|
}
|
|
};
|
|
|
|
/* ********************************************************************
|
|
* global public variables
|
|
*/
|
|
CipDlrObject g_dlr; /**< definition of DLR object instance 1 data */
|
|
|
|
|
|
/* ********************************************************************
|
|
* local functions
|
|
*/
|
|
static void EncodeCipRingSupervisorConfig(const void *const data,
|
|
ENIPMessage *const outgoing_message) {
|
|
/* Suppress unused parameter compiler warning. */
|
|
(void)data;
|
|
|
|
const size_t kRingSupStructSize = 12u;
|
|
FillNextNMessageOctetsWithValueAndMoveToNextPosition(0,
|
|
kRingSupStructSize,
|
|
outgoing_message);
|
|
}
|
|
|
|
static void EncodeCipNodeAddress(const void *const data,
|
|
ENIPMessage *const outgoing_message) {
|
|
CipNodeAddress *node_address = (CipNodeAddress *)data;
|
|
EncodeCipUdint(&node_address->device_ip, outgoing_message);
|
|
EncodeCipEthernetLinkPhyisicalAddress(&node_address->device_mac,
|
|
outgoing_message);
|
|
}
|
|
|
|
|
|
/* ********************************************************************
|
|
* public functions
|
|
*/
|
|
EipStatus CipDlrInit(void) {
|
|
CipClass *dlr_class = NULL;
|
|
|
|
dlr_class = CreateCipClass(kCipDlrClassCode,
|
|
0, /* # class attributes */
|
|
7, /* # highest class attribute number */
|
|
2, /* # class services */
|
|
11,/* # instance attributes */
|
|
12,/* # of highest instance attribute */
|
|
2, /* # instance services */
|
|
1, /* # instances */
|
|
"DLR", /* object class name */
|
|
DLR_CLASS_REVISION, /* # class revision */
|
|
NULL /* function pointer for initialization */
|
|
);
|
|
|
|
if (NULL == dlr_class) {
|
|
return kEipStatusError;
|
|
}
|
|
|
|
/* Add services to the class */
|
|
InsertService(dlr_class, kGetAttributeSingle,
|
|
GetAttributeSingle, "GetAttributeSingle");
|
|
InsertService(dlr_class, kGetAttributeAll,
|
|
GetAttributeAll, "GetAttributeAll");
|
|
|
|
/* Bind attributes to the instance */
|
|
CipInstance *dlr_instance = GetCipInstance(dlr_class, 1u);
|
|
|
|
InsertAttribute(dlr_instance,
|
|
1,
|
|
kCipUsint,
|
|
EncodeCipUsint,
|
|
NULL,
|
|
&g_dlr.network_topology,
|
|
kGetableSingleAndAll);
|
|
InsertAttribute(dlr_instance,
|
|
2,
|
|
kCipUsint,
|
|
EncodeCipUsint,
|
|
NULL,
|
|
&g_dlr.network_status,
|
|
kGetableSingleAndAll);
|
|
InsertAttribute(dlr_instance,
|
|
3,
|
|
kCipUsint,
|
|
EncodeCipUsint,
|
|
NULL,
|
|
(void *)&s_0xFF_default,
|
|
kGetableAll);
|
|
InsertAttribute(dlr_instance,
|
|
4,
|
|
kCipAny,
|
|
EncodeCipRingSupervisorConfig,
|
|
NULL,
|
|
(void *)&s_0x00000000_default,
|
|
kGetableAllDummy);
|
|
InsertAttribute(dlr_instance,
|
|
5,
|
|
kCipUint,
|
|
EncodeCipUint,
|
|
NULL,
|
|
(void *)&s_0x0000_default,
|
|
kGetableAll);
|
|
InsertAttribute(dlr_instance,
|
|
6,
|
|
kCipAny,
|
|
EncodeCipNodeAddress,
|
|
NULL,
|
|
(void *)&s_zero_node,
|
|
kGetableAll);
|
|
InsertAttribute(dlr_instance,
|
|
7,
|
|
kCipAny,
|
|
EncodeCipNodeAddress,
|
|
NULL,
|
|
(void *)&s_zero_node,
|
|
kGetableAll);
|
|
InsertAttribute(dlr_instance,
|
|
8,
|
|
kCipUint,
|
|
EncodeCipUint,
|
|
NULL,
|
|
(void *)&s_0xFFFF_default,
|
|
kGetableAll);
|
|
/* Attribute #9 is not implemented and also NOT part of the GetAttributesAll
|
|
* response. Therefore it is not added here! */
|
|
InsertAttribute(dlr_instance,
|
|
10,
|
|
kCipAny,
|
|
EncodeCipNodeAddress,
|
|
NULL,
|
|
&g_dlr.active_supervisor_address,
|
|
kGetableSingleAndAll);
|
|
InsertAttribute(dlr_instance,
|
|
11,
|
|
kCipUsint,
|
|
EncodeCipUsint,
|
|
NULL,
|
|
(void *)&s_0x00_default,
|
|
kGetableAll);
|
|
InsertAttribute(dlr_instance,
|
|
12,
|
|
kCipDword,
|
|
EncodeCipDword,
|
|
NULL,
|
|
&g_dlr.capability_flags,
|
|
kGetableSingleAndAll);
|
|
|
|
/* Set attributes to initial values */
|
|
/* Assume beacon based DLR device. Also all Revision 3 and higher devices
|
|
* are required to support the Flush_Tables and Learning_Update frames
|
|
* (see Vol. 2 Section 5-6.2 Revision History of the DLR object).*/
|
|
g_dlr.capability_flags = (kDlrCapBeaconBased | kDlrCapFlushTableFrame);
|
|
|
|
return kEipStatusOk;
|
|
}
|