cipdlr.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*******************************************************************************
  2. * Copyright (c) 2019, Rockwell Automation, Inc.
  3. * All rights reserved.
  4. *
  5. ******************************************************************************/
  6. /** @file
  7. * @brief Implements the DLR object
  8. * @author Stefan Maetje <stefan.maetje@esd.eu>
  9. *
  10. * CIP DLR object
  11. * ==============
  12. *
  13. * This module implements the DLR object for a non supervisor and non gateway
  14. * device.
  15. *
  16. * Implemented Attributes
  17. * ----------------------
  18. * - Attribute 1: Network Topology
  19. * - Attribute 2: Network Status
  20. * - Attribute 10: Active Supervisor Address
  21. * - Attribute 12: Capability Flags
  22. *
  23. * Non-implemented attributes
  24. * --------------------------
  25. * The attributes 3, 4, 5, 6, 7, 8, 9 and 11 are only required for devices
  26. * that are capable of functioning as a ring supervisor. These attributes
  27. * shall not be implemented by non-supervisor devices.
  28. *
  29. * The attributes 13, 14, 15 and 16 are only required for devices that are
  30. * capable of functioning as a redundant gateway. These attributes shall
  31. * not be implemented by non-redundant gateway devices.
  32. *
  33. * None of the attributes 17, 18 and 19 is required and implemented.
  34. * Because of this the Object Revision stays on level 3 (see @ref
  35. * DLR_CLASS_REVISION).
  36. *
  37. * Implemented Services
  38. * --------------------
  39. * - GetAttributesAll
  40. * - GetAttributeSingle
  41. */
  42. /* ********************************************************************
  43. * include files
  44. */
  45. #include "cipdlr.h"
  46. #include <string.h>
  47. #include "cipcommon.h"
  48. #include "opener_api.h"
  49. #include "trace.h"
  50. #include "endianconv.h"
  51. /* ********************************************************************
  52. * defines
  53. */
  54. /** The implemented class revision is still 3 because the attributes
  55. * mandatory for revision 4 are NOT implemented. */
  56. #define DLR_CLASS_REVISION 3
  57. /* ********************************************************************
  58. * Type declarations
  59. */
  60. /* ********************************************************************
  61. * module local variables
  62. */
  63. /* Define variables with default values to be used for the
  64. * GetAttributeAll response for not implemented attributes. */
  65. static const CipUsint s_0xFF_default = 0xFFU;
  66. static const CipUint s_0xFFFF_default = 0xFFFFU;
  67. static const CipUsint s_0x00_default = 0x00U;
  68. static const CipUint s_0x0000_default = 0x0000U;
  69. static const CipUdint s_0x00000000_default = 0x00000000U;
  70. static const CipNodeAddress s_zero_node = {
  71. .device_ip = 0,
  72. .device_mac = {
  73. 0, 0, 0, 0, 0, 0,
  74. }
  75. };
  76. /* ********************************************************************
  77. * global public variables
  78. */
  79. CipDlrObject g_dlr; /**< definition of DLR object instance 1 data */
  80. /* ********************************************************************
  81. * local functions
  82. */
  83. static void EncodeCipRingSupervisorConfig(const void *const data,
  84. ENIPMessage *const outgoing_message) {
  85. /* Suppress unused parameter compiler warning. */
  86. (void)data;
  87. const size_t kRingSupStructSize = 12u;
  88. FillNextNMessageOctetsWithValueAndMoveToNextPosition(0,
  89. kRingSupStructSize,
  90. outgoing_message);
  91. }
  92. static void EncodeCipNodeAddress(const void *const data,
  93. ENIPMessage *const outgoing_message) {
  94. CipNodeAddress *node_address = (CipNodeAddress *)data;
  95. EncodeCipUdint(&node_address->device_ip, outgoing_message);
  96. EncodeCipEthernetLinkPhyisicalAddress(&node_address->device_mac,
  97. outgoing_message);
  98. }
  99. /* ********************************************************************
  100. * public functions
  101. */
  102. EipStatus CipDlrInit(void) {
  103. CipClass *dlr_class = NULL;
  104. dlr_class = CreateCipClass(kCipDlrClassCode,
  105. 0, /* # class attributes */
  106. 7, /* # highest class attribute number */
  107. 2, /* # class services */
  108. 11,/* # instance attributes */
  109. 12,/* # of highest instance attribute */
  110. 2, /* # instance services */
  111. 1, /* # instances */
  112. "DLR", /* object class name */
  113. DLR_CLASS_REVISION, /* # class revision */
  114. NULL /* function pointer for initialization */
  115. );
  116. if (NULL == dlr_class) {
  117. return kEipStatusError;
  118. }
  119. /* Add services to the class */
  120. InsertService(dlr_class, kGetAttributeSingle,
  121. GetAttributeSingle, "GetAttributeSingle");
  122. InsertService(dlr_class, kGetAttributeAll,
  123. GetAttributeAll, "GetAttributeAll");
  124. /* Bind attributes to the instance */
  125. CipInstance *dlr_instance = GetCipInstance(dlr_class, 1u);
  126. InsertAttribute(dlr_instance,
  127. 1,
  128. kCipUsint,
  129. EncodeCipUsint,
  130. NULL,
  131. &g_dlr.network_topology,
  132. kGetableSingleAndAll);
  133. InsertAttribute(dlr_instance,
  134. 2,
  135. kCipUsint,
  136. EncodeCipUsint,
  137. NULL,
  138. &g_dlr.network_status,
  139. kGetableSingleAndAll);
  140. InsertAttribute(dlr_instance,
  141. 3,
  142. kCipUsint,
  143. EncodeCipUsint,
  144. NULL,
  145. (void *)&s_0xFF_default,
  146. kGetableAll);
  147. InsertAttribute(dlr_instance,
  148. 4,
  149. kCipAny,
  150. EncodeCipRingSupervisorConfig,
  151. NULL,
  152. (void *)&s_0x00000000_default,
  153. kGetableAllDummy);
  154. InsertAttribute(dlr_instance,
  155. 5,
  156. kCipUint,
  157. EncodeCipUint,
  158. NULL,
  159. (void *)&s_0x0000_default,
  160. kGetableAll);
  161. InsertAttribute(dlr_instance,
  162. 6,
  163. kCipAny,
  164. EncodeCipNodeAddress,
  165. NULL,
  166. (void *)&s_zero_node,
  167. kGetableAll);
  168. InsertAttribute(dlr_instance,
  169. 7,
  170. kCipAny,
  171. EncodeCipNodeAddress,
  172. NULL,
  173. (void *)&s_zero_node,
  174. kGetableAll);
  175. InsertAttribute(dlr_instance,
  176. 8,
  177. kCipUint,
  178. EncodeCipUint,
  179. NULL,
  180. (void *)&s_0xFFFF_default,
  181. kGetableAll);
  182. /* Attribute #9 is not implemented and also NOT part of the GetAttributesAll
  183. * response. Therefore it is not added here! */
  184. InsertAttribute(dlr_instance,
  185. 10,
  186. kCipAny,
  187. EncodeCipNodeAddress,
  188. NULL,
  189. &g_dlr.active_supervisor_address,
  190. kGetableSingleAndAll);
  191. InsertAttribute(dlr_instance,
  192. 11,
  193. kCipUsint,
  194. EncodeCipUsint,
  195. NULL,
  196. (void *)&s_0x00_default,
  197. kGetableAll);
  198. InsertAttribute(dlr_instance,
  199. 12,
  200. kCipDword,
  201. EncodeCipDword,
  202. NULL,
  203. &g_dlr.capability_flags,
  204. kGetableSingleAndAll);
  205. /* Set attributes to initial values */
  206. /* Assume beacon based DLR device. Also all Revision 3 and higher devices
  207. * are required to support the Flush_Tables and Learning_Update frames
  208. * (see Vol. 2 Section 5-6.2 Revision History of the DLR object).*/
  209. g_dlr.capability_flags = (kDlrCapBeaconBased | kDlrCapFlushTableFrame);
  210. return kEipStatusOk;
  211. }