Bladeren bron

Merge branch 'micsat-master'

Martin Melik Merkumians 4 jaren geleden
bovenliggende
commit
c847745926

File diff suppressed because it is too large
+ 46 - 46
data/OpENerPC.stc


+ 77 - 101
source/src/cip/cipassembly.c

@@ -14,15 +14,21 @@
 #include "trace.h"
 #include "cipconnectionmanager.h"
 
-/** @brief Implementation of the SetAttributeSingle CIP service for Assembly
- *          Objects.
+/** @brief Retrieve the given data according to CIP encoding from the
+ * 		message buffer.
+ *
+ *  Implementation of the decode function for the SetAttributeSingle CIP service for Assembly
+ *  Objects.
  *  Currently only supports Attribute 3 (CIP_BYTE_ARRAY) of an Assembly
+ *  @param data pointer to value to be written.
+ *  @param message_router_request pointer to the request where the data should be taken from
+ *  @param message_router_response pointer to the response where status should be set
+ *  @return length of taken bytes
+ *          -1 .. error
  */
-EipStatus SetAssemblyAttributeSingle(CipInstance *const instance,
-                                     const CipMessageRouterRequest *const message_router_request,
-                                     CipMessageRouterResponse *const message_router_response,
-                                     const struct sockaddr *originator_address,
-                                     const int encapsulation_session);
+int DecodeCipAssemblyAttribute3(CipByteArray *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response);
 
 static EipStatus AssemblyPreGetCallback
 (
@@ -56,18 +62,18 @@ CipClass *CreateAssemblyClass(void) {
                                             "assembly", /* name */
                                             2, /* Revision, according to the CIP spec currently this has to be 2 */
                                             NULL); /* # function pointer for initialization*/
-  if(NULL != assembly_class) {
-    InsertService(assembly_class,
-                  kGetAttributeSingle,
-                  &GetAttributeSingle,
-                  "GetAttributeSingle");
-    InsertService(assembly_class,
-                  kSetAttributeSingle,
-                  &SetAssemblyAttributeSingle,
-                  "SetAssemblyAttributeSingle");
-    InsertGetSetCallback(assembly_class, AssemblyPreGetCallback, kPreGetFunc);
-    InsertGetSetCallback(assembly_class, AssemblyPostSetCallback, kPostSetFunc);
-  }
+	if (NULL != assembly_class) {
+		InsertService(assembly_class, kGetAttributeSingle, &GetAttributeSingle,
+				"GetAttributeSingle");
+
+		InsertService(assembly_class, kSetAttributeSingle, &SetAttributeSingle,
+				"SetAttributeSingle");
+
+		InsertGetSetCallback(assembly_class, AssemblyPreGetCallback,
+				kPreGetFunc);
+		InsertGetSetCallback(assembly_class, AssemblyPostSetCallback,
+				kPostSetFunc);
+	}
 
   return assembly_class;
 }
@@ -117,17 +123,21 @@ CipInstance *CreateAssemblyObject(const EipUint32 instance_id,
 
   assembly_byte_array->length = data_length;
   assembly_byte_array->data = data;
+
   InsertAttribute(instance,
                   3,
                   kCipByteArray,
                   EncodeCipByteArray,
+                  DecodeCipAssemblyAttribute3,
                   assembly_byte_array,
                   kSetAndGetAble | kPreGetFunc | kPostSetFunc);
   /* Attribute 4 Number of bytes in Attribute 3 */
+
   InsertAttribute(instance,
                   4,
                   kCipUint,
                   EncodeCipUint,
+                  NULL,
                   &(assembly_byte_array->length),
                   kGetableSingle);
 
@@ -153,88 +163,54 @@ EipStatus NotifyAssemblyConnectedDataReceived(CipInstance *const instance,
   return AfterAssemblyDataReceived(instance);
 }
 
-EipStatus SetAssemblyAttributeSingle(CipInstance *const instance,
-                                     const CipMessageRouterRequest *const message_router_request,
-                                     CipMessageRouterResponse *const message_router_response,
-                                     const struct sockaddr *originator_address,
-                                     const int encapsulation_session) {
-  OPENER_TRACE_INFO(" setAttribute %d\n",
-                    message_router_request->request_path.attribute_number);
-
-  const EipUint8 *const router_request_data = message_router_request->data;
-
-  message_router_response->reply_service =
-    (0x80 | message_router_request->service);
-  message_router_response->general_status = kCipErrorAttributeNotSupported;
-  message_router_response->size_of_additional_status = 0;
-
-  CipAttributeStruct *attribute = GetCipAttribute(instance,
-                                                  message_router_request->request_path.attribute_number);
-
-  if( (attribute != NULL) &&
-      (3 == message_router_request->request_path.attribute_number) ) {
-    if(attribute->data != NULL) {
-      const CipByteArray *const data = (CipByteArray *) attribute->data;
-
-      /* TODO: check for ATTRIBUTE_SET/GETABLE MASK */
-      if( true == IsConnectedOutputAssembly(instance->instance_number) ) {
-        OPENER_TRACE_WARN(
-          "Assembly AssemblyAttributeSingle: received data for connected output assembly\n\r");
-        message_router_response->general_status = kCipErrorAttributeNotSetable;
-      }
-      else{
-        if(message_router_request->request_path_size < data->length) {
-          OPENER_TRACE_INFO(
-            "Assembly setAssemblyAttributeSingle: not enough data received.\r\n");
-          message_router_response->general_status = kCipErrorNotEnoughData;
-        }
-        else{
-          if(message_router_request->request_path_size > data->length) {
-            OPENER_TRACE_INFO(
-              "Assembly setAssemblyAttributeSingle: too much data received.\r\n");
-            message_router_response->general_status = kCipErrorTooMuchData;
-          }
-          else{
-            if ( (attribute->attribute_flags & kPreSetFunc)
-                 && instance->cip_class->PreSetCallback ) {
-              instance->cip_class->PreSetCallback(instance,
-                                                  attribute,
-                                                  message_router_request->service);
-            }
-
-            memcpy(data->data, router_request_data, data->length);
-
-            if(AfterAssemblyDataReceived(instance) != kEipStatusOk) {
-              /* punt early without updating the status... though I don't know
-               * how much this helps us here, as the attribute's data has already
-               * been overwritten.
-               *
-               * however this is the task of the application side which will
-               * take the data. In addition we have to inform the sender that the
-               * data was not ok.
-               */
-              message_router_response->general_status =
-                kCipErrorInvalidAttributeValue;
-            }
-            else{
-              message_router_response->general_status = kCipErrorSuccess;
-            }
-          }
-        }
-      }
-    }
-    else{
-      /* the attribute was zero we are a heartbeat assembly */
-      message_router_response->general_status = kCipErrorTooMuchData;
-    }
-  }
-
-  if( (attribute != NULL) &&
-      (4 == message_router_request->request_path.attribute_number) ) {
-    message_router_response->general_status = kCipErrorAttributeNotSetable;
-  }
-
-  return kEipStatusOkSend;
+int DecodeCipAssemblyAttribute3(CipByteArray *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response) {
+
+	const EipUint8 **const cip_message = message_router_request->data;
+
+	CipInstance *const instance = GetCipInstance(
+			GetCipClass(message_router_request->request_path.class_id),
+			message_router_request->request_path.instance_number);
+
+	int number_of_decoded_bytes = -1;
+	OPENER_TRACE_INFO(" -> set Assembly attribute byte array\r\n");
+	CipByteArray *cip_byte_array = data;
+
+	if (message_router_request->request_path_size < data->length) {
+		OPENER_TRACE_INFO(
+				"DecodeCipByteArray: not enough data received.\n");
+		message_router_response->general_status = kCipErrorNotEnoughData;
+		return number_of_decoded_bytes;
+	}
+	if (message_router_request->request_path_size > data->length) {
+		OPENER_TRACE_INFO(
+				"DecodeCipByteArray: too much data received.\n");
+		message_router_response->general_status = kCipErrorTooMuchData;
+		return number_of_decoded_bytes;
+	}
+
+	// data-length is correct
+	memcpy(cip_byte_array->data, cip_message, cip_byte_array->length);
+
+	if (AfterAssemblyDataReceived(instance) != kEipStatusOk) {
+		/* punt early without updating the status... though I don't know
+		 * how much this helps us here, as the attribute's data has already
+		 * been overwritten.
+		 *
+		 * however this is the task of the application side which will
+		 * take the data. In addition we have to inform the sender that the
+		 * data was not ok.
+		 */
+		message_router_response->general_status =
+				kCipErrorInvalidAttributeValue;
+	} else {
+		message_router_response->general_status = kCipErrorSuccess;
+	}
+
+	number_of_decoded_bytes = cip_byte_array->length;
+
+	return number_of_decoded_bytes;
 }
 
 static EipStatus AssemblyPreGetCallback

File diff suppressed because it is too large
+ 361 - 322
source/src/cip/cipcommon.c


+ 26 - 0
source/src/cip/cipcommon.h

@@ -58,6 +58,32 @@ EipStatus GetAttributeSingle(
   const struct sockaddr *originator_address,
   const int encapsulation_session);
 
+void GenerateSetAttributeSingleHeader(
+  const CipMessageRouterRequest *const message_router_request,
+  CipMessageRouterResponse *const message_router_response);
+
+/** @brief Generic implementation of the SetAttributeSingle CIP service
+ *
+ *  Modifies an attribute value if the requested object has
+ *  the appropriate attribute implemented and if the attribute is setable.
+ *
+ * @param instance pointer to instance.
+ * @param message_router_request pointer to request.
+ * @param message_router_response pointer to response.
+ * @param originator_address address struct of the originator as received
+ * @param encapsulation_session associated encapsulation session of the explicit message
+ * @return status  >0 .. success
+ *          -1 .. requested attribute not set
+ */
+EipStatus SetAttributeSingle(
+  CipInstance *RESTRICT const instance,
+  CipMessageRouterRequest *const
+  message_router_request,
+  CipMessageRouterResponse *const
+  message_router_response,
+  const struct sockaddr *originator_address,
+  const int encapsulation_session);
+
 /** @brief Generic implementation of the GetAttributeAll CIP service
  *
  * Copy all attributes from Object into the global message buffer.

+ 8 - 10
source/src/cip/cipconnectionmanager.c

@@ -175,20 +175,20 @@ void InitializeConnectionManager(CipClass *class) {
 
   CipClass *meta_class = class->class_instance.cip_class;
 
-  InsertAttribute( (CipInstance *) class, 1, kCipUint, EncodeCipUint,
+  InsertAttribute( (CipInstance *) class, 1, kCipUint, EncodeCipUint, NULL,
                    (void *) &class->revision, kGetableSingleAndAll );                                                /* revision */
-  InsertAttribute( (CipInstance *) class, 2, kCipUint, EncodeCipUint,
+  InsertAttribute( (CipInstance *) class, 2, kCipUint, EncodeCipUint, NULL,
                    (void *) &class->number_of_instances, kGetableSingleAndAll );                                                /*  largest instance number */
-  InsertAttribute( (CipInstance *) class, 3, kCipUint, EncodeCipUint,
+  InsertAttribute( (CipInstance *) class, 3, kCipUint, EncodeCipUint, NULL,
                    (void *) &class->number_of_instances, kGetableSingle );                                                /* number of instances currently existing*/
-  InsertAttribute( (CipInstance *) class, 4, kCipUint, EncodeCipUint,
+  InsertAttribute( (CipInstance *) class, 4, kCipUint, EncodeCipUint, NULL,
                    (void *) &kCipUintZero, kNotSetOrGetable );                                                /* optional attribute list - default = 0 */
-  InsertAttribute( (CipInstance *) class, 5, kCipUint, EncodeCipUint,
+  InsertAttribute( (CipInstance *) class, 5, kCipUint, EncodeCipUint, NULL,
                    (void *) &kCipUintZero, kNotSetOrGetable );                                                /* optional service list - default = 0 */
-  InsertAttribute( (CipInstance *) class, 6, kCipUint, EncodeCipUint,
+  InsertAttribute( (CipInstance *) class, 6, kCipUint, EncodeCipUint, NULL,
                    (void *) &meta_class->highest_attribute_number,
                    kGetableSingleAndAll );                                                                                                /* max class attribute number*/
-  InsertAttribute( (CipInstance *) class, 7, kCipUint, EncodeCipUint,
+  InsertAttribute( (CipInstance *) class, 7, kCipUint, EncodeCipUint, NULL,
                    (void *) &class->highest_attribute_number,
                    kGetableSingleAndAll );                                                                                           /* max instance attribute number*/
 
@@ -229,9 +229,7 @@ EipStatus ConnectionManagerInit(EipUint16 unique_connection_id) {
                 &GetAttributeAll,
                 "GetAttributeAll");
   InsertService(connection_manager, kForwardOpen, &ForwardOpen, "ForwardOpen");
-  InsertService(connection_manager,
-                kLargeForwardOpen,
-                &LargeForwardOpen,
+  InsertService(connection_manager, kLargeForwardOpen, &LargeForwardOpen,
                 "LargeForwardOpen");
   InsertService(connection_manager, kForwardClose, &ForwardClose,
                 "ForwardClose");

+ 15 - 1
source/src/cip/cipdlr.c

@@ -143,45 +143,56 @@ EipStatus CipDlrInit(void) {
                   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,
+  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
@@ -190,18 +201,21 @@ EipStatus CipDlrInit(void) {
                   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);
 

+ 103 - 109
source/src/cip/cipethernetlink.c

@@ -36,9 +36,11 @@
  *
  *  - GetAttributesAll
  *  - GetAttributeSingle
- *    - GetAndClearAttribute  (0 != OPENER_ETHLINK_CNTRS_ENABLE)
+ *  - GetAndClearAttribute  (0 != OPENER_ETHLINK_CNTRS_ENABLE)
  *        This service should only implemented for the attributes 4, 5, 12,
  *        13 and 15.
+ *  - SetAttributeSingle (0 != OPENER_ETHLINK_IFACE_CTRL_ENABLE)
+ *  		This service should only be implemented if attribute 6 is enabled.
  *
  */
 
@@ -110,12 +112,19 @@ EipStatus GetAndClearEthernetLink(
 
 #if defined(OPENER_ETHLINK_IFACE_CTRL_ENABLE) && \
   0 != OPENER_ETHLINK_IFACE_CTRL_ENABLE
-EipStatus SetAttributeSingleEthernetLink(
-  CipInstance *instance,
-  CipMessageRouterRequest *message_router_request,
-  CipMessageRouterResponse *message_router_response,
-  const struct sockaddr *originator_address,
-  const int encapsulation_session);
+
+/** @brief Modify the attribute values for Attribute6: Interface Control
+ *
+ * @param CipEthernetLinkInterfaceControl pointer to attribute data.
+ * @param message_router_request pointer to request.
+ * @param message_router_response pointer to response.
+ * @return length of taken bytes
+ *          -1 .. error
+ */
+int DecodeCipEthernetLinkInterfaceControl(
+		CipEthernetLinkInterfaceControl *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response);
 #endif
 
 
@@ -253,6 +262,7 @@ EipStatus CipEthernetLinkInit(void) {
                   "GetAttributeSingle");
     InsertService(ethernet_link_class, kGetAttributeAll, &GetAttributeAll,
                   "GetAttributeAll");
+
 #if defined(OPENER_ETHLINK_CNTRS_ENABLE) && 0 != OPENER_ETHLINK_CNTRS_ENABLE
     InsertService(ethernet_link_class, kEthLinkGetAndClear,
                   &GetAndClearEthernetLink, "GetAndClear");
@@ -260,8 +270,8 @@ EipStatus CipEthernetLinkInit(void) {
 #if defined(OPENER_ETHLINK_IFACE_CTRL_ENABLE) && \
     0 != OPENER_ETHLINK_IFACE_CTRL_ENABLE
     InsertService(ethernet_link_class, kSetAttributeSingle,
-                  &SetAttributeSingleEthernetLink,
-                  "SetAttributeSingleEthernetLink");
+    				&SetAttributeSingle,
+                      "SetAttributeSingle");
 #endif
 
     /* bind attributes to the instance */
@@ -273,18 +283,21 @@ EipStatus CipEthernetLinkInit(void) {
                       1,
                       kCipUdint,
                       EncodeCipUdint,
+                      NULL,
                       &g_ethernet_link[idx].interface_speed,
                       kGetableSingleAndAll);
       InsertAttribute(ethernet_link_instance,
                       2,
                       kCipDword,
                       EncodeCipDword,
+                      NULL,
                       &g_ethernet_link[idx].interface_flags,
                       kGetableSingleAndAll);
       InsertAttribute(ethernet_link_instance,
                       3,
                       kCip6Usint,
                       EncodeCipEthernetLinkPhyisicalAddress,
+                      NULL,
                       &g_ethernet_link[idx].physical_address,
                       kGetableSingleAndAll);
 #if defined(OPENER_ETHLINK_CNTRS_ENABLE) && 0 != OPENER_ETHLINK_CNTRS_ENABLE
@@ -292,21 +305,29 @@ EipStatus CipEthernetLinkInit(void) {
                       4,
                       kCipUsint,
                       EncodeCipUsint,
+                      NULL,
                       &g_ethernet_link[idx].interface_cntrs,
                       kGetableSingleAndAll);
-      InsertAttribute(ethernet_link_instance, 5, kCipUsint, EncodeCipUsint,
-                      &g_ethernet_link[idx].media_cntrs, kGetableSingleAndAll);
+      InsertAttribute(ethernet_link_instance,
+                      5,
+                      kCipUsint,
+                      EncodeCipUsint,
+                      NULL,
+                      &g_ethernet_link[idx].media_cntrs,
+                      kGetableSingleAndAll);
 #else
       InsertAttribute(ethernet_link_instance,
                       4,
                       kCipAny,
                       EncodeCipEthernetLinkInterfaceCounters,
+                      NULL,
                       &dummy_attribute_udint,
                       kGetableAllDummy);
       InsertAttribute(ethernet_link_instance,
                       5,
                       kCipAny,
                       EncodeCipEthernetLinkMediaCounters,
+                      NULL,
                       &dummy_attribute_udint,
                       kGetableAllDummy);
 #endif  /* ... && 0 != OPENER_ETHLINK_CNTRS_ENABLE */
@@ -318,6 +339,7 @@ EipStatus CipEthernetLinkInit(void) {
                         6,
                         kCipAny,
                         EncodeCipEthernetLinkInterfaceControl,
+                        DecodeCipEthernetLinkInterfaceControl,
                         &g_ethernet_link[idx].interface_control,
                         IFACE_CTRL_ACCESS_MODE & ~kSetable);
       } else {
@@ -325,6 +347,7 @@ EipStatus CipEthernetLinkInit(void) {
                         6,
                         kCipAny,
                         EncodeCipEthernetLinkInterfaceControl,
+                        DecodeCipEthernetLinkInterfaceControl,
                         &g_ethernet_link[idx].interface_control,
                         IFACE_CTRL_ACCESS_MODE);
       }
@@ -333,26 +356,42 @@ EipStatus CipEthernetLinkInit(void) {
                       6,
                       kCipAny,
                       EncodeCipEthernetLinkInterfaceControl,
+                      NULL,
                       &s_interface_control,
                       kGetableAll);
 #endif
-      InsertAttribute(ethernet_link_instance, 7, kCipUsint, EncodeCipUsint,
+      InsertAttribute(ethernet_link_instance,
+                      7,
+                      kCipUsint,
+                      EncodeCipUsint,
+                      NULL,
                       &g_ethernet_link[idx].interface_type,
                       kGetableSingleAndAll);
-      InsertAttribute(ethernet_link_instance, 8, kCipUsint, EncodeCipUsint,
-                      &dummy_attribute_usint, kGetableAllDummy);
-      InsertAttribute(ethernet_link_instance, 9, kCipUsint, EncodeCipUsint,
+      InsertAttribute(ethernet_link_instance,
+                      8,
+                      kCipUsint,
+                      EncodeCipUsint,
+                      NULL,
+                      &dummy_attribute_usint,
+                      kGetableAllDummy);
+      InsertAttribute(ethernet_link_instance,
+                      9,
+                      kCipUsint,
+                      EncodeCipUsint,
+                      NULL,
                       &dummy_attribute_usint, kGetableAllDummy);
       InsertAttribute(ethernet_link_instance,
                       10,
                       kCipShortString,
                       EncodeCipShortString,
+                      NULL,
                       &g_ethernet_link[idx].interface_label,
                       IFACE_LABEL_ACCESS_MODE);
       InsertAttribute(ethernet_link_instance,
                       11,
                       kCipAny,
                       EncodeCipEthernetLinkInterfaceCaps,
+                      NULL,
                       &g_ethernet_link[idx].interface_caps,
                       kGetableSingleAndAll);
     }
@@ -507,7 +546,7 @@ static bool IsIfaceControlAllowed(CipUdint instance_id,
                                   CipEthernetLinkInterfaceControl const *iface_cntrl)
 {
   const CipUsint duplex_mode =
-    (iface_cntrl->control_bits & kEthLinkIfCntrlForcedDuplex) ? 1 : 0;
+    (iface_cntrl->control_bits & kEthLinkIfCntrlForceDuplexFD) ? 1 : 0;
   for (size_t i = 0; i < NELEMENTS(speed_duplex_table); i++) {
     if (g_ethernet_link[instance_id - 1].interface_caps.speed_duplex_selector &
         (1U << i) ) {
@@ -521,97 +560,52 @@ static bool IsIfaceControlAllowed(CipUdint instance_id,
   return false;
 }
 
-EipStatus SetAttributeSingleEthernetLink(
-  CipInstance *instance,
-  CipMessageRouterRequest *message_router_request,
-  CipMessageRouterResponse *message_router_response,
-  const struct sockaddr *originator_address,
-  const int encapsulation_session) {
-  CipAttributeStruct *attribute = GetCipAttribute(
-    instance, message_router_request->request_path.attribute_number);
-  EipUint16 attribute_number = message_router_request->request_path
-                               .attribute_number;
-
-  if (NULL != attribute) {
-    uint8_t set_bit_mask = (instance->cip_class->set_bit_mask[CalculateIndex(
-                                                                attribute_number)
-                            ]);
-    if ( set_bit_mask & ( 1 << ( (attribute_number) % 8 ) ) ) {
-
-      if (attribute->attribute_flags & kPreSetFunc
-          && instance->cip_class->PreSetCallback) {
-        instance->cip_class->PreSetCallback(instance,
-                                            attribute,
-                                            message_router_request->service);
-      }
-
-      OPENER_TRACE_INFO(" setAttribute %d\n", attribute_number);
-      switch (attribute_number) {
-        case 6: {
-          CipEthernetLinkInterfaceControl if_cntrl;
-          (void)DecodeData(kCipWord, &if_cntrl.control_bits,
-                           &(message_router_request->data) );
-          (void)DecodeData(kCipUint, &if_cntrl.forced_interface_speed,
-                           &(message_router_request->data) );
-
-          if (if_cntrl.control_bits > kEthLinkIfCntrlMaxValid) {
-            message_router_response->general_status =
-              kCipErrorInvalidAttributeValue;
-
-          } else {
-            if ( (0 !=
-                  (if_cntrl.control_bits & kEthLinkIfCntrlAutonegotiate) ) &&
-                 ( (0 !=
-                    (if_cntrl.control_bits & kEthLinkIfCntrlForcedDuplex) ) ||
-                   (0 != if_cntrl.forced_interface_speed) ) ) {
-              message_router_response->general_status =
-                kCipErrorObjectStateConflict;
-            } else {
-              if (0 ==
-                  (if_cntrl.control_bits & kEthLinkIfCntrlAutonegotiate) ) {
-                /* Need to check if a supported mode is forced. */
-                if (!IsIfaceControlAllowed(instance->instance_number,
-                                           &if_cntrl) ) {
-                  message_router_response->general_status =
-                    kCipErrorInvalidAttributeValue;
-                  break;
-                }
-              }
-              CipEthernetLinkInterfaceControl *data = attribute->data;
-              *(data) = if_cntrl;
-              message_router_response->general_status = kCipErrorSuccess;
-            }
-          }
-        }
-        break;
-
-        default:
-          message_router_response->general_status =
-            kCipErrorAttributeNotSetable;
-          break;
-      }
-
-      /* Call the PostSetCallback if enabled. */
-      if (attribute->attribute_flags & (kPostSetFunc | kNvDataFunc)
-          && NULL != instance->cip_class->PostSetCallback) {
-        CipUsint service = message_router_request->service;
-        if (kCipErrorSuccess != message_router_response->general_status) {
-          service |= 0x80;    /* Flag no update, TODO: remove this workaround */
-        }
-        instance->cip_class->PostSetCallback(instance, attribute, service);
-      }
-    } else {
-      message_router_response->general_status = kCipErrorAttributeNotSetable;
-    }
-  } else {
-    /* we don't have this attribute or only accessible via GetAttributesAll */
-    message_router_response->general_status = kCipErrorAttributeNotSupported;
-  }
-
-  message_router_response->size_of_additional_status = 0;
-  message_router_response->data_length = 0;
-  message_router_response->reply_service = (0x80
-                                            | message_router_request->service);
-  return kEipStatusOkSend;
+int DecodeCipEthernetLinkInterfaceControl(
+		CipEthernetLinkInterfaceControl *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response) {
+
+	CipInstance *const instance = GetCipInstance(
+				GetCipClass(message_router_request->request_path.class_id),
+				message_router_request->request_path.instance_number);
+
+	int number_of_decoded_bytes = -1;
+
+	CipEthernetLinkInterfaceControl if_cntrl;
+
+	DecodeCipWord(&if_cntrl.control_bits, message_router_request,
+			message_router_response);
+	DecodeCipUint(&if_cntrl.forced_interface_speed, message_router_request,
+			message_router_response);
+
+	if (if_cntrl.control_bits > kEthLinkIfCntrlMaxValid) {
+		message_router_response->general_status =
+				kCipErrorInvalidAttributeValue;
+		return number_of_decoded_bytes;
+
+	} else {
+		if ((0 != (if_cntrl.control_bits & kEthLinkIfCntrlAutonegotiate))
+				&& ((0 != (if_cntrl.control_bits & kEthLinkIfCntrlForceDuplexFD))
+						|| (0 != if_cntrl.forced_interface_speed))) {
+			message_router_response->general_status =
+					kCipErrorObjectStateConflict;
+			return number_of_decoded_bytes;
+		} else {
+			if (0 == (if_cntrl.control_bits & kEthLinkIfCntrlAutonegotiate)) {
+				/* Need to check if a supported mode is forced. */
+				if (!IsIfaceControlAllowed(instance->instance_number,
+						&if_cntrl)) {
+					message_router_response->general_status =
+							kCipErrorInvalidAttributeValue;
+					return number_of_decoded_bytes;
+				}
+			}
+			*data = if_cntrl; //write data to attribute
+			message_router_response->general_status = kCipErrorSuccess;
+			number_of_decoded_bytes = 4;
+		}
+	}
+	return number_of_decoded_bytes;
 }
-#endif
+
+ #endif

+ 14 - 7
source/src/cip/cipidentity.c

@@ -189,25 +189,25 @@ void InitializeCipIdentity(CipClass *class) {
   CipClass *meta_class = class->class_instance.cip_class;
 
   InsertAttribute( (CipInstance *) class, 1, kCipUint,
-                   EncodeCipUint,
+                   EncodeCipUint, NULL,
                    (void *) &class->revision,
                    kGetableSingleAndAll );                 /* revision */
   InsertAttribute( (CipInstance *) class, 2, kCipUint,
-                   EncodeCipUint,
+                   EncodeCipUint, NULL,
                    (void *) &class->number_of_instances, kGetableSingleAndAll ); /*  largest instance number */
   InsertAttribute( (CipInstance *) class, 3, kCipUint,
-                   EncodeCipUint,
+                   EncodeCipUint, NULL,
                    (void *) &class->number_of_instances, kGetableSingle ); /* number of instances currently existing*/
-  InsertAttribute( (CipInstance *) class, 4, kCipUint, EncodeCipUint,
+  InsertAttribute( (CipInstance *) class, 4, kCipUint, EncodeCipUint, NULL,
                    (void *) &kCipUintZero,
                    kNotSetOrGetable ); /* optional attribute list - default = 0 */
-  InsertAttribute( (CipInstance *) class, 5, kCipUint, EncodeCipUint,
+  InsertAttribute( (CipInstance *) class, 5, kCipUint, EncodeCipUint, NULL,
                    (void *) &kCipUintZero,
                    kNotSetOrGetable ); /* optional service list - default = 0 */
-  InsertAttribute( (CipInstance *) class, 6, kCipUint, EncodeCipUint,
+  InsertAttribute( (CipInstance *) class, 6, kCipUint, EncodeCipUint, NULL,
                    (void *) &meta_class->highest_attribute_number,
                    kGetableSingleAndAll );                 /* max class attribute number*/
-  InsertAttribute( (CipInstance *) class, 7, kCipUint, EncodeCipUint,
+  InsertAttribute( (CipInstance *) class, 7, kCipUint, EncodeCipUint, NULL,
                    (void *) &class->highest_attribute_number,
                    kGetableSingleAndAll );                 /* max instance attribute number*/
 
@@ -248,42 +248,49 @@ EipStatus CipIdentityInit() {
                   1,
                   kCipUint,
                   EncodeCipUint,
+				  NULL,
                   &g_identity.vendor_id,
                   kGetableSingleAndAll);
   InsertAttribute(instance,
                   2,
                   kCipUint,
                   EncodeCipUint,
+				  NULL,
                   &g_identity.device_type,
                   kGetableSingleAndAll);
   InsertAttribute(instance,
                   3,
                   kCipUint,
                   EncodeCipUint,
+				  NULL,
                   &g_identity.product_code,
                   kGetableSingleAndAll);
   InsertAttribute(instance,
                   4,
                   kCipUsintUsint,
                   EncodeRevision,
+				  NULL,
                   &g_identity.revision,
                   kGetableSingleAndAll);
   InsertAttribute(instance,
                   5,
                   kCipWord,
                   EncodeCipWord,
+				  NULL,
                   &g_identity.status,
                   kGetableSingleAndAll);
   InsertAttribute(instance,
                   6,
                   kCipUdint,
                   EncodeCipUdint,
+				  NULL,
                   &g_identity.serial_number,
                   kGetableSingleAndAll);
   InsertAttribute(instance,
                   7,
                   kCipShortString,
                   EncodeCipShortString,
+				  NULL,
                   &g_identity.product_name,
                   kGetableSingleAndAll);
 

+ 7 - 7
source/src/cip/cipmessagerouter.c

@@ -54,24 +54,24 @@ void InitializeCipMessageRouterClass(CipClass *cip_class) {
 
   CipClass *meta_class = cip_class->class_instance.cip_class;
 
-  InsertAttribute( (CipInstance *) cip_class, 1, kCipUint, EncodeCipUint,
+  InsertAttribute( (CipInstance *) cip_class, 1, kCipUint, EncodeCipUint, NULL,
                    (void *) &cip_class->revision, kGetableSingleAndAll );   /* revision */
-  InsertAttribute( (CipInstance *) cip_class, 2, kCipUint, EncodeCipUint,
+  InsertAttribute( (CipInstance *) cip_class, 2, kCipUint, EncodeCipUint, NULL,
                    (void *) &cip_class->number_of_instances,
                    kGetableSingle );                                       /*  largest instance number */
-  InsertAttribute( (CipInstance *) cip_class, 3, kCipUint, EncodeCipUint,
+  InsertAttribute( (CipInstance *) cip_class, 3, kCipUint, EncodeCipUint, NULL,
                    (void *) &cip_class->number_of_instances,
                    kGetableSingle );                                                           /* number of instances currently existing*/
-  InsertAttribute( (CipInstance *) cip_class, 4, kCipUint, EncodeCipUint,
+  InsertAttribute( (CipInstance *) cip_class, 4, kCipUint, EncodeCipUint, NULL,
                    (void *) &kCipUintZero,
                    kGetableAll );   /* optional attribute list - default = 0 */
-  InsertAttribute( (CipInstance *) cip_class, 5, kCipUint, EncodeCipUint,
+  InsertAttribute( (CipInstance *) cip_class, 5, kCipUint, EncodeCipUint, NULL,
                    (void *) &kCipUintZero,
                    kGetableAll ); /* optional service list - default = 0 */
-  InsertAttribute( (CipInstance *) cip_class, 6, kCipUint, EncodeCipUint,
+  InsertAttribute( (CipInstance *) cip_class, 6, kCipUint, EncodeCipUint, NULL,
                    (void *) &meta_class->highest_attribute_number,
                    kGetableSingleAndAll );                       /* max class attribute number*/
-  InsertAttribute( (CipInstance *) cip_class, 7, kCipUint, EncodeCipUint,
+  InsertAttribute( (CipInstance *) cip_class, 7, kCipUint, EncodeCipUint, NULL,
                    (void *) &cip_class->highest_attribute_number,
                    kGetableSingleAndAll );                       /* max instance attribute number*/
 

+ 51 - 61
source/src/cip/cipqos.c

@@ -55,67 +55,49 @@ static CipQosDscpValues s_active_dscp = {
 };
 
 /************** Functions ****************************************/
-EipStatus SetAttributeSingleQoS(
-  CipInstance *instance,
-  CipMessageRouterRequest *message_router_request,
-  CipMessageRouterResponse *message_router_response,
-  const struct sockaddr *originator_address,
-  const int encapsulation_session) {
-
-  CipAttributeStruct *attribute = GetCipAttribute(
-    instance, message_router_request->request_path.attribute_number);
-  (void) instance;   /*Suppress compiler warning */
-  EipUint16 attribute_number =
-    message_router_request->request_path.attribute_number;
-  uint8_t set_bit_mask = (instance->cip_class->set_bit_mask[CalculateIndex(
-                                                              attribute_number)
-                          ]);
-
-  if( NULL != attribute &&
-      ( set_bit_mask & ( 1 << ( (attribute_number) % 8 ) ) ) ) {
-    CipUsint attribute_value_received = GetUsintFromMessage(
-      &(message_router_request->data) );
-
-    if( attribute_value_received < 64U ) {
-      OPENER_TRACE_INFO(" setAttribute %d\n", attribute_number);
-
-      if(NULL != attribute->data) {
-        /* Call the PreSetCallback if enabled. */
-        if ( (attribute->attribute_flags & kPreSetFunc)
-             && NULL != instance->cip_class->PreSetCallback ) {
-          instance->cip_class->PreSetCallback(instance, attribute,
-                                              message_router_request->service);
-        }
-
-        CipUsint *data = (CipUsint *) attribute->data;
-        *(data) = attribute_value_received;
-
-        /* Call the PostSetCallback if enabled. */
-        if ( (attribute->attribute_flags & (kPostSetFunc | kNvDataFunc) )
-             && NULL != instance->cip_class->PostSetCallback ) {
-          instance->cip_class->PostSetCallback(instance, attribute,
-                                               message_router_request->service);
-        }
-
-        message_router_response->general_status = kCipErrorSuccess;
-      } else {
-        message_router_response->general_status = kCipErrorNotEnoughData;
-        OPENER_TRACE_INFO("CIP QoS not enough data\n");
-      }
-    } else {
-      message_router_response->general_status = kCipErrorInvalidAttributeValue;
-    }
-  } else {
-    /* we don't have this attribute */
-    message_router_response->general_status = kCipErrorAttributeNotSupported;
-  }
 
-  message_router_response->size_of_additional_status = 0;
-  InitializeENIPMessage(&message_router_response->message);
-  message_router_response->reply_service = (0x80
-                                            | message_router_request->service);
 
-  return kEipStatusOkSend;
+/**@brief Retrieve the given data according to CIP encoding from the
+ * 		message buffer.
+ *
+ *  Implementation of the decode function for the SetAttributeSingle CIP service for QoS
+ *  Objects.
+ *  @param data pointer to value to be written.
+ *  @param message_router_request pointer to the request where the data should be taken from
+ *  @param message_router_response pointer to the response where status should be set
+ *  @return length of taken bytes
+ *          -1 .. error
+ */
+int DecodeCipQoSAttribute(CipUsint *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response) {
+
+	const EipUint8 **const cip_message = message_router_request->data;
+
+	int number_of_decoded_bytes = -1;
+
+	if (NULL != cip_message) {
+
+		CipUsint attribute_value_received = GetUsintFromMessage(&cip_message);
+		if (attribute_value_received < 64U) {
+
+			*data = attribute_value_received; //write value to attribute
+
+			message_router_response->general_status = kCipErrorSuccess;
+			number_of_decoded_bytes = 1;
+
+		} else {
+			message_router_response->general_status =
+					kCipErrorInvalidAttributeValue;
+		}
+	} else {
+
+		message_router_response->general_status = kCipErrorNotEnoughData;
+		OPENER_TRACE_INFO("CIP QoS not enough data\n");
+	}
+
+	return number_of_decoded_bytes;
+
 }
 
 CipUsint CipQosGetDscpPriority(ConnectionObjectPriority priority) {
@@ -168,55 +150,63 @@ EipStatus CipQoSInit() {
                   1,
                   kCipUsint,
                   EncodeCipUsint,
+                  NULL,
                   (void *) &g_qos.q_frames_enable,
                   kNotSetOrGetable);
   InsertAttribute(instance,
                   2,
                   kCipUsint,
                   EncodeCipUsint,
+                  NULL,
                   (void *) &g_qos.dscp.event,
                   kNotSetOrGetable);
   InsertAttribute(instance,
                   3,
                   kCipUsint,
                   EncodeCipUsint,
+                  NULL,
                   (void *) &g_qos.dscp.general,
                   kNotSetOrGetable);
   InsertAttribute(instance,
                   4,
                   kCipUsint,
                   EncodeCipUsint,
+                  DecodeCipQoSAttribute,
                   (void *) &g_qos.dscp.urgent,
                   kGetableSingle | kSetable | kNvDataFunc);
   InsertAttribute(instance,
                   5,
                   kCipUsint,
                   EncodeCipUsint,
+                  DecodeCipQoSAttribute,
                   (void *) &g_qos.dscp.scheduled,
                   kGetableSingle | kSetable | kNvDataFunc);
   InsertAttribute(instance,
                   6,
                   kCipUsint,
                   EncodeCipUsint,
+                  DecodeCipQoSAttribute,
                   (void *) &g_qos.dscp.high,
                   kGetableSingle | kSetable | kNvDataFunc);
   InsertAttribute(instance,
                   7,
                   kCipUsint,
                   EncodeCipUsint,
+                  DecodeCipQoSAttribute,
                   (void *) &g_qos.dscp.low,
                   kGetableSingle | kSetable | kNvDataFunc);
   InsertAttribute(instance,
                   8,
                   kCipUsint,
                   EncodeCipUsint,
+                  DecodeCipQoSAttribute,
                   (void *) &g_qos.dscp.explicit_msg,
                   kGetableSingle | kSetable | kNvDataFunc);
 
   InsertService(qos_class, kGetAttributeSingle, &GetAttributeSingle,
                 "GetAttributeSingle");
-  InsertService(qos_class, kSetAttributeSingle, &SetAttributeSingleQoS,
-                "SetAttributeSingleQoS");
+  InsertService(qos_class, kSetAttributeSingle, &SetAttributeSingle,
+                  "SetAttributeSingle");
 
   return kEipStatusOk;
 }

+ 215 - 209
source/src/cip/ciptcpipinterface.c

@@ -313,7 +313,7 @@ static CipUsint dummy_data_field = 0; /**< dummy data fiel to provide non-null d
 
 /************** Functions ****************************************/
 
-void EncoodeCipTcpIpInterfaceConfiguration(const void *const data,
+void EncodeCipTcpIpInterfaceConfiguration(const void *const data,
                                            ENIPMessage *const outgoing_message)
 {
   CipTcpIpInterfaceConfiguration *
@@ -362,214 +362,170 @@ void EncodeCipLastConflictDetected(const void *const data,
                                                        outgoing_message);
 }
 
-EipStatus SetAttributeSingleTcpIpInterface(
-  CipInstance *instance,
-  CipMessageRouterRequest *message_router_request,
-  CipMessageRouterResponse *message_router_response,
-  const struct sockaddr *originator_address,
-  const int encapsulation_session) {
-  CipAttributeStruct *attribute = GetCipAttribute(
-    instance, message_router_request->request_path.attribute_number);
-  EipUint16 attribute_number = message_router_request->request_path
-                               .attribute_number;
-
-  /* Check attribute exists and is not a dummy for GetAttributeAll */
-  if (NULL != attribute && !(kGetableAllDummy & attribute->attribute_flags) ) {
-    uint8_t set_bit_mask = (instance->cip_class->set_bit_mask[CalculateIndex(
-                                                                attribute_number)
-                            ]);
-    if ( set_bit_mask & ( 1 << ( (attribute_number) % 8 ) ) ) {
-
-      if ( (attribute->attribute_flags & kPreSetFunc)
-           && instance->cip_class->PreSetCallback ) {
-        instance->cip_class->PreSetCallback(instance,
-                                            attribute,
-                                            message_router_request->service);
-      }
-
-      switch (attribute_number) {
-        case 3: {
-          CipDword configuration_control_received = GetUdintFromMessage(
-            &(message_router_request->data) );
-          if ( (configuration_control_received & kTcpipCfgCtrlMethodMask) >=
-               0x03 ||
-               (configuration_control_received & ~kTcpipCfgCtrlMethodMask) ) {
-            message_router_response->general_status =
-              kCipErrorInvalidAttributeValue;
-
-          } else {
-
-            OPENER_TRACE_INFO(" setAttribute %d\n", attribute_number);
-
-            if (attribute->data != NULL) {
-              CipDword *data = (CipDword *) attribute->data;
-              /* Set reserved bits to zero on reception. */
-              configuration_control_received &=
-                (kTcpipCfgCtrlMethodMask | kTcpipCfgCtrlDnsEnable);
-              *(data) = configuration_control_received;
-              message_router_response->general_status = kCipErrorSuccess;
-            } else {
-              message_router_response->general_status = kCipErrorNotEnoughData;
-            }
-          }
-        }
-        break;
+
+int DecodeTcpIpInterfaceConfigurationControl( /* Attribute 3 */
+		CipDword *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response) {
+
+	int number_of_decoded_bytes = -1;
+
+	CipDword configuration_control_received = GetDintFromMessage(
+			&(message_router_request->data));
+	if ((configuration_control_received & kTcpipCfgCtrlMethodMask) >= 0x03
+			|| (configuration_control_received & ~kTcpipCfgCtrlMethodMask)) {
+		message_router_response->general_status =
+				kCipErrorInvalidAttributeValue;
+
+	} else {
+
+		/* Set reserved bits to zero on reception. */
+		configuration_control_received &= (kTcpipCfgCtrlMethodMask
+				| kTcpipCfgCtrlDnsEnable);
+
+		*data = configuration_control_received;
+		number_of_decoded_bytes = 4;
+		message_router_response->general_status = kCipErrorSuccess;
+	}
+
+	return number_of_decoded_bytes;
+}
 
 #if defined (OPENER_TCPIP_IFACE_CFG_SETTABLE) && \
           0 != OPENER_TCPIP_IFACE_CFG_SETTABLE
-        case 5: { /* Interface configuration */
-          CipTcpIpInterfaceConfiguration if_cfg;
-          CipUdint tmp_ip;
-
-          if (IsIOConnectionActive() ) {
-            message_router_response->general_status =
-              kCipErrorDeviceStateConflict;
-            break;
-          }
-          if (kTcpipCfgCtrlStaticIp !=
-              (g_tcpip.config_control & kTcpipCfgCtrlMethodMask) ) {
-            message_router_response->general_status =
-              kCipErrorObjectStateConflict;
-            break;
-          }
-          memset(&if_cfg, 0, sizeof if_cfg);
-          tmp_ip = GetUdintFromMessage(&(message_router_request->data) );
-          if_cfg.ip_address = htonl(tmp_ip);
-          tmp_ip = GetUdintFromMessage(&(message_router_request->data) );
-          if_cfg.network_mask = htonl(tmp_ip);
-          tmp_ip = GetUdintFromMessage(&(message_router_request->data) );
-          if_cfg.gateway = htonl(tmp_ip);
-          tmp_ip = GetUdintFromMessage(&(message_router_request->data) );
-          if_cfg.name_server = htonl(tmp_ip);
-          tmp_ip = GetUdintFromMessage(&(message_router_request->data) );
-          if_cfg.name_server_2 = htonl(tmp_ip);
-
-          CipUint domain_name_length =
-            GetUintFromMessage(&(message_router_request->data) );
-          if (domain_name_length > 48) {  /* see Vol. 2, Table 5-4.3 Instance Attributes */
-            message_router_response->general_status = kCipErrorTooMuchData;
-            break;
-          }
-          SetCipStringByData(&if_cfg.domain_name,
-                             domain_name_length,
-                             message_router_request->data);
-          domain_name_length = (domain_name_length + 1) & (~0x0001u);  /* Align for possible pad byte */
-          OPENER_TRACE_INFO("Domain: ds %hu '%s'\n",
-                            domain_name_length,
-                            if_cfg.domain_name.string);
-          message_router_request->data += domain_name_length;
-
-          if (!IsValidNetworkConfig(&if_cfg) ||
-              (domain_name_length > 0 &&
-               !IsValidDomain(if_cfg.domain_name.string) ) ) {
-            message_router_response->general_status =
-              kCipErrorInvalidAttributeValue;
-            break;
-          }
-          OPENER_TRACE_INFO(" setAttribute %d\n", attribute_number);
-          CipTcpIpInterfaceConfiguration *const p_interface_configuration =
-            (CipTcpIpInterfaceConfiguration *)attribute->data;
-          /* Free first and then making a shallow copy of if_cfg.domain_name is ok,
-           * because if_cfg goes out of scope now. */
-          FreeCipString(&p_interface_configuration->domain_name);
-          *p_interface_configuration = if_cfg;
-          /* Tell that this configuration change becomes active after a reset */
-          g_tcpip.status |= kTcpipStatusIfaceCfgPend;
-          message_router_response->general_status = kCipErrorSuccess;
-        }
-        break;
-
-        case 6: { /* host name */
-          CipString tmp_host_name = {
-            .length = 0u,
-            .string = NULL
-          };
-          CipUint host_name_length =
-            GetUintFromMessage(&(message_router_request->data) );
-          if (host_name_length > 64) {  /* see RFC 1123 on more details */
-            message_router_response->general_status = kCipErrorTooMuchData;
-            break;
-          }
-          SetCipStringByData(&tmp_host_name,
-                             host_name_length,
-                             message_router_request->data);
-          host_name_length = (host_name_length + 1) & (~0x0001u);  /* Align for possible pad byte */
-          OPENER_TRACE_INFO("Host Name: ds %hu '%s'\n",
-                            host_name_length,
-                            tmp_host_name.string);
-          message_router_request->data += host_name_length;
-          if (!IsValidNameLabel(tmp_host_name.string) ) {
-            message_router_response->general_status =
-              kCipErrorInvalidAttributeValue;
-            break;
-          }
-          OPENER_TRACE_INFO(" setAttribute %d\n", attribute_number);
-          CipString *const host_name = (CipString *)attribute->data;
-          /* Free first and then making a shallow copy of tmp_host_name is ok,
-           * because tmp_host_name goes out of scope now. */
-          FreeCipString(host_name);
-          *host_name = tmp_host_name;
-          /* Tell that this configuration change becomes active after a reset */
-          g_tcpip.status |= kTcpipStatusIfaceCfgPend;
-          message_router_response->general_status = kCipErrorSuccess;
-        }
-        break;
+
+int DecodeCipTcpIpInterfaceConfiguration( /* Attribute 5 */
+		CipTcpIpInterfaceConfiguration *const data, //kCipUdintUdintUdintUdintUdintString
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response) {
+
+	int number_of_decoded_bytes = -1;
+
+	CipTcpIpInterfaceConfiguration if_cfg;
+	CipUdint tmp_ip;
+
+	if (IsIOConnectionActive()) {
+		message_router_response->general_status = kCipErrorDeviceStateConflict;
+		return number_of_decoded_bytes;
+	}
+	if (kTcpipCfgCtrlStaticIp
+			!= (g_tcpip.config_control & kTcpipCfgCtrlMethodMask)) {
+		message_router_response->general_status = kCipErrorObjectStateConflict;
+		return number_of_decoded_bytes;
+	}
+	memset(&if_cfg, 0, sizeof if_cfg);
+	tmp_ip = GetUdintFromMessage(&(message_router_request->data));
+	if_cfg.ip_address = htonl(tmp_ip);
+	tmp_ip = GetUdintFromMessage(&(message_router_request->data));
+	if_cfg.network_mask = htonl(tmp_ip);
+	tmp_ip = GetUdintFromMessage(&(message_router_request->data));
+	if_cfg.gateway = htonl(tmp_ip);
+	tmp_ip = GetUdintFromMessage(&(message_router_request->data));
+	if_cfg.name_server = htonl(tmp_ip);
+	tmp_ip = GetUdintFromMessage(&(message_router_request->data));
+	if_cfg.name_server_2 = htonl(tmp_ip);
+
+	CipUint domain_name_length = GetUintFromMessage(
+			&(message_router_request->data));
+	if (domain_name_length > 48) { /* see Vol. 2, Table 5-4.3 Instance Attributes */
+		message_router_response->general_status = kCipErrorTooMuchData;
+		return number_of_decoded_bytes;
+	}
+	SetCipStringByData(&if_cfg.domain_name, domain_name_length,
+			message_router_request->data);
+	domain_name_length = (domain_name_length + 1) & (~0x0001u); /* Align for possible pad byte */
+	OPENER_TRACE_INFO("Domain: ds %hu '%s'\n",
+			domain_name_length,
+			if_cfg.domain_name.string);
+
+	if (!IsValidNetworkConfig(&if_cfg)
+			|| (domain_name_length > 0
+					&& !IsValidDomain(if_cfg.domain_name.string))) {
+		message_router_response->general_status =
+				kCipErrorInvalidAttributeValue;
+		return number_of_decoded_bytes;
+	}
+
+	*data = if_cfg; //write data to attribute
+	number_of_decoded_bytes = 20 + domain_name_length;
+
+	/* Tell that this configuration change becomes active after a reset */
+	g_tcpip.status |= kTcpipStatusIfaceCfgPend;
+	message_router_response->general_status = kCipErrorSuccess;
+
+	return number_of_decoded_bytes;
+
+}
+
+int DecodeCipTcpIpInterfaceHostName( /* Attribute 6 */
+		CipString *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response) {
+
+	int number_of_decoded_bytes = -1;
+
+	          CipString tmp_host_name = {
+	            .length = 0u,
+	            .string = NULL
+	          };
+	          CipUint host_name_length =
+	            GetUintFromMessage(&(message_router_request->data) );
+	          if (host_name_length > 64) {  /* see RFC 1123 on more details */
+	            message_router_response->general_status = kCipErrorTooMuchData;
+	            return number_of_decoded_bytes;
+	          }
+	          SetCipStringByData(&tmp_host_name,
+	                             host_name_length,
+	                             message_router_request->data);
+	          host_name_length = (host_name_length + 1) & (~0x0001u);  /* Align for possible pad byte */
+	          OPENER_TRACE_INFO("Host Name: ds %hu '%s'\n",
+	                            host_name_length,
+	                            tmp_host_name.string);
+
+	          if (!IsValidNameLabel(tmp_host_name.string) ) {
+	            message_router_response->general_status =
+	              kCipErrorInvalidAttributeValue;
+	            return number_of_decoded_bytes;
+	          }
+
+	          *data = tmp_host_name; //write data to attribute
+
+	          /* Tell that this configuration change becomes active after a reset */
+	          g_tcpip.status |= kTcpipStatusIfaceCfgPend;
+	          message_router_response->general_status = kCipErrorSuccess;
+
+	return number_of_decoded_bytes;
+
+}
+
 #endif /* defined (OPENER_TCPIP_IFACE_CFG_SETTABLE) && 0 != OPENER_TCPIP_IFACE_CFG_SETTABLE*/
 
-        case 13: {
-
-          CipUint inactivity_timeout_received = GetUintFromMessage(
-            &(message_router_request->data) );
-
-          if (inactivity_timeout_received > 3600) {
-            message_router_response->general_status =
-              kCipErrorInvalidAttributeValue;
-          } else {
-
-            OPENER_TRACE_INFO("setAttribute %d\n", attribute_number);
-
-            if (attribute->data != NULL) {
-              CipUint *data = (CipUint *) attribute->data;
-
-              *(data) = inactivity_timeout_received;
-              message_router_response->general_status = kCipErrorSuccess;
-            } else {
-              message_router_response->general_status = kCipErrorNotEnoughData;
-            }
-          }
-        }
-        break;
-
-        default:
-          message_router_response->general_status =
-            kCipErrorAttributeNotSetable;
-          break;
-      }
-
-      /* Call the PostSetCallback if enabled. */
-      if ( (attribute->attribute_flags & (kPostSetFunc | kNvDataFunc) )
-           && NULL != instance->cip_class->PostSetCallback ) {
-        CipUsint service = message_router_request->service;
-        if (kCipErrorSuccess != message_router_response->general_status) {
-          service |= 0x80;    /* Flag no update, TODO: remove this workaround*/
-        }
-        instance->cip_class->PostSetCallback(instance, attribute, service);
-      }
-    } else {
-      message_router_response->general_status = kCipErrorAttributeNotSetable;
-    }
-  } else {
-    /* we don't have this attribute */
-    message_router_response->general_status = kCipErrorAttributeNotSupported;
-  }
+int DecodeCipTcpIpInterfaceEncapsulationInactivityTimeout( /* Attribute 13 */
+		CipUint *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response) {
+
+	int number_of_decoded_bytes = -1;
+
+	CipUint inactivity_timeout_received = GetUintFromMessage(
+			&(message_router_request->data));
+
+	if (inactivity_timeout_received > 3600) {
+		message_router_response->general_status =
+				kCipErrorInvalidAttributeValue;
+	} else {
+
+		*data = inactivity_timeout_received;
+		message_router_response->general_status = kCipErrorSuccess;
+		number_of_decoded_bytes = 2;
+
+	}
+
+	return number_of_decoded_bytes;
 
-  message_router_response->size_of_additional_status = 0;
-  InitializeENIPMessage(&message_router_response->message);
-  message_router_response->reply_service = (0x80
-                                            | message_router_request->service);
-  return kEipStatusOkSend;
 }
 
+
 EipStatus CipTcpIpInterfaceInit() {
   CipClass *tcp_ip_class = NULL;
 
@@ -589,66 +545,116 @@ EipStatus CipTcpIpInterfaceInit() {
 
   CipInstance *instance = GetCipInstance(tcp_ip_class, 1); /* bind attributes to the instance #1 that was created above */
 
-  InsertAttribute(instance, 1, kCipDword, EncodeCipDword, &g_tcpip.status,
+  InsertAttribute(instance,
+                  1,
+                  kCipDword,
+                  EncodeCipDword,
+                  NULL,
+                  &g_tcpip.status,
                   kGetableSingleAndAll);
   InsertAttribute(instance,
                   2,
                   kCipDword,
                   EncodeCipDword,
+                  NULL,
                   &g_tcpip.config_capability,
                   kGetableSingleAndAll);
   InsertAttribute(instance,
                   3,
                   kCipDword,
                   EncodeCipDword,
+                  DecodeTcpIpInterfaceConfigurationControl,
                   &g_tcpip.config_control,
                   kSetAndGetAble | kNvDataFunc | IFACE_CFG_SET_MODE );
   InsertAttribute(instance,
                   4,
                   kCipEpath,
                   EncodeCipEPath,
+                  NULL,
                   &g_tcpip.physical_link_object,
                   kGetableSingleAndAll);
+
+#if defined (OPENER_TCPIP_IFACE_CFG_SETTABLE) && \
+          0 != OPENER_TCPIP_IFACE_CFG_SETTABLE
   InsertAttribute(instance,
                   5,
                   kCipUdintUdintUdintUdintUdintString,
-                  EncoodeCipTcpIpInterfaceConfiguration,
+                  EncodeCipTcpIpInterfaceConfiguration,
+                  DecodeCipTcpIpInterfaceConfiguration,
                   &g_tcpip.interface_configuration,
                   kGetableSingleAndAll | kNvDataFunc | IFACE_CFG_SET_MODE);
-  InsertAttribute(instance, 6, kCipString, EncodeCipString, &g_tcpip.hostname,
+  InsertAttribute(instance,
+                  6,
+                  kCipString,
+                  EncodeCipString,
+                  DecodeCipTcpIpInterfaceHostName,
+                  &g_tcpip.hostname,
                   kGetableSingleAndAll | kNvDataFunc | IFACE_CFG_SET_MODE);
+
+#else
+  InsertAttribute(instance,
+                  5,
+                  kCipUdintUdintUdintUdintUdintString,
+                  EncodeCipTcpIpInterfaceConfiguration,
+                  NULL, //not settable
+                  &g_tcpip.interface_configuration,
+                  kGetableSingleAndAll | kNvDataFunc | IFACE_CFG_SET_MODE);
+    InsertAttribute(instance,
+                  6,
+                  kCipString,
+                  EncodeCipString,
+                  NULL, //not settable
+                  &g_tcpip.hostname,
+                  kGetableSingleAndAll | kNvDataFunc | IFACE_CFG_SET_MODE);
+
+#endif /* defined (OPENER_TCPIP_IFACE_CFG_SETTABLE) && 0 != OPENER_TCPIP_IFACE_CFG_SETTABLE*/
+
   InsertAttribute(instance,
                   7,
                   kCipAny,
                   EncodeSafetyNetworkNumber,
+                  NULL,
                   &dummy_data_field,
                   kGetableAllDummy);
   InsertAttribute(instance,
                   8,
                   kCipUsint,
                   EncodeCipUsint,
+                  NULL,
                   &g_tcpip.mcast_ttl_value,
                   kGetableSingleAndAll);
   InsertAttribute(instance,
                   9,
                   kCipAny,
                   EncodeCipTcpIpMulticastConfiguration,
+                  NULL,
                   &g_tcpip.mcast_config,
                   kGetableSingleAndAll);
-  InsertAttribute(instance, 10, kCipBool, EncodeCipBool, &g_tcpip.select_acd,
+  InsertAttribute(instance,
+                  10,
+                  kCipBool,
+                  EncodeCipBool,
+                  NULL,
+                  &g_tcpip.select_acd,
                   kGetableAllDummy);
   InsertAttribute(instance,
                   11,
                   kCipBool,
                   EncodeCipLastConflictDetected,
+                  NULL,
                   &dummy_data_field,
                   kGetableAllDummy);
-  InsertAttribute(instance, 12, kCipBool, EncodeCipBool, &dummy_data_field,
-                  kGetableAllDummy);
+  InsertAttribute(instance,
+                  12,
+                  kCipBool,
+                  EncodeCipBool,
+                  NULL,
+                  &dummy_data_field, kGetableAllDummy);
   InsertAttribute(instance,
                   13,
                   kCipUint,
                   EncodeCipUint,
+                  DecodeCipTcpIpInterfaceEncapsulationInactivityTimeout,
                   &g_tcpip.encapsulation_inactivity_timeout,
                   kSetAndGetAble | kNvDataFunc);
 
@@ -660,8 +666,8 @@ EipStatus CipTcpIpInterfaceInit() {
                 "GetAttributeAll");
 
   InsertService(tcp_ip_class, kSetAttributeSingle,
-                &SetAttributeSingleTcpIpInterface,
-                "SetAttributeSingleTcpIpInterface");
+                &SetAttributeSingle,
+                "SetAttributeSingle");
 
   return kEipStatusOk;
 }

+ 8 - 1
source/src/cip/ciptypes.h

@@ -99,7 +99,8 @@ typedef enum {
   kLargeForwardOpen = 0x5B,
   kForwardClose = 0x4E,
   kUnconnectedSend = 0x52,
-  kGetConnectionOwner = 0x5A
+  kGetConnectionOwner = 0x5A,
+  kGetConnectionData = 0x56
 /* End CIP object-specific services */
 } CIPServiceCode;
 
@@ -275,12 +276,18 @@ typedef struct {
 typedef void (*CipAttributeEncodeInMessage)(const void *const data,
                                             ENIPMessage *const outgoing_message);
 
+/** @brief self-describing data decoding for CIP types */
+typedef int (*CipAttributeDecodeFromMessage)(const void *const data,
+									const CipMessageRouterRequest *const message_router_request,
+									CipMessageRouterResponse *const message_router_response);
+
 /** @brief Structure to describe a single CIP attribute of an object
  */
 typedef struct {
   EipUint16 attribute_number; /**< The attribute number of this attribute. */
   EipUint8 type;  /**< The @ref CipDataType of this attribute. */
   CipAttributeEncodeInMessage encode; /**< Self-describing its data encoding */
+  CipAttributeDecodeFromMessage decode; /**< Self-describing its data decoding */
   CIPAttributeFlag attribute_flags; /**< See @ref CIPAttributeFlag declaration for valid values. */
   void *data;
 } CipAttributeStruct;

+ 7 - 0
source/src/enet_encap/endianconv.c

@@ -47,6 +47,13 @@ CipUsint GetUsintFromMessage(const CipOctet **const buffer_address) {
   return data;
 }
 
+CipBool GetBoolFromMessage(const EipBool8 **const buffer_address) {
+  const EipBool8 *buffer = *buffer_address;
+  EipBool8 data = buffer[0];
+  *buffer_address += 1;
+  return data;
+}
+
 /* little-endian-to-host unsigned 16 bit*/
 
 /**

+ 2 - 0
source/src/enet_encap/endianconv.h

@@ -30,6 +30,8 @@ CipByte GetByteFromMessage(const CipOctet **const buffer_address);
 
 CipUsint GetUsintFromMessage(const CipOctet **const buffer_address);
 
+CipBool GetBoolFromMessage(const EipBool8 **const buffer_address);
+
 /** @ingroup ENCAP
  *
  * @brief Get an 16Bit integer from the network buffer, and moves pointer beyond the 16 bit value

+ 78 - 7
source/src/opener_api.h

@@ -224,6 +224,7 @@ CipInstance *AddCipInstance(CipClass *RESTRICT const cip_class_to_add_instance,
  *  @param attribute_number Number of attribute to be inserted.
  *  @param cip_data_type Type of attribute to be inserted.
  *  @param encode_function Function pointer to the encoding function
+ *  @param decode_function Function pointer to the decoding function
  *  @param cip_data Pointer to data of attribute.
  *  @param cip_flags Flags to indicate set-ability and get-ability of attribute.
  */
@@ -231,6 +232,7 @@ void InsertAttribute(CipInstance *const instance,
                      const EipUint16 attribute_number,
                      const EipUint8 cip_type,
                      CipAttributeEncodeInMessage encode_function,
+					 CipAttributeDecodeFromMessage decode_function,
                      void *const data,
                      const EipByte cip_flags);
 
@@ -367,21 +369,90 @@ void EncodeCipEPath(const CipEpath *const data,
 void EncodeCipEthernetLinkPhyisicalAddress(const void *const data,
                                            ENIPMessage *const outgoing_message);
 
+
 /** @ingroup CIP_API
  * @brief Retrieve the given data according to CIP encoding from the message
  * buffer.
  *
- * This function may be used in in own services for handling data from the
+ * This function may be used in own services for handling data from the
  * requester (e.g., setAttributeSingle).
- *  @param cip_data_type the CIP type to decode
- *  @param cip_data pointer to data value to written.
- *  @param cip_message pointer to memory where the data should be taken from
+ *  @param data pointer to value to be written.
+ *  @param message_router_request pointer to the request where the data should be taken from
+ *  @param message_router_response pointer to the response where status should be set
  *  @return length of taken bytes
  *          -1 .. error
  */
-int DecodeData(const EipUint8 cip_data_type,
-               void *const cip_data,
-               const EipUint8 **const cip_message);
+int DecodeCipBool(CipBool *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response);
+
+int DecodeCipByte(CipByte *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response);
+
+int DecodeCipByteArray(CipByteArray *const data,
+			const CipMessageRouterRequest *const message_router_request,
+			CipMessageRouterResponse *const message_router_response);
+
+int DecodeCipWord(CipWord *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response);
+
+int DecodeCipDword(CipDword *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response);
+
+int DecodeCipLword(CipLword *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response);
+
+int DecodeCipUsint(CipUsint *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response);
+
+int DecodeCipUint(CipUint *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response);
+
+int DecodeCipUdint(CipUdint *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response);
+
+int DecodeCipUlint(CipUlint *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response);
+
+int DecodeCipSint(CipSint *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response);
+
+int DecodeCipInt(CipInt *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response);
+
+int DecodeCipDint(CipDint *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response);
+
+int DecodeCipLint(CipLint *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response);
+
+int DecodeCipReal(CipReal *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response);
+
+int DecodeCipLreal(CipLreal *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response);
+
+int DecodeCipString(CipString *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response);
+
+int DecodeCipShortString(CipShortString *const data,
+		const CipMessageRouterRequest *const message_router_request,
+		CipMessageRouterResponse *const message_router_response);
 
 /** @ingroup CIP_API
  * @brief Create an instance of an assembly object

+ 3 - 0
source/src/ports/generic_networkhandler.c

@@ -27,6 +27,8 @@
 #include "cipqos.h"
 #include "udp_protocol.h"
 
+#include "../../cip_objects/OpENerFileObject/cipfile.h"
+
 #define MAX_NO_OF_TCP_SOCKETS 10
 
 /* ----- Windows size_t PRI macros ------------- */
@@ -433,6 +435,7 @@ EipStatus NetworkHandlerProcessOnce(void) {
   if(g_network_status.elapsed_time >= kOpenerTimerTickInMilliSeconds) {
     /* call manage_connections() in connection manager every kOpenerTimerTickInMilliSeconds ms */
     ManageConnections(g_network_status.elapsed_time);
+    CipFileSessionTimerCheck(g_network_status.elapsed_time);
     g_network_status.elapsed_time = 0;
   }
   return kEipStatusOk;

Some files were not shown because too many files changed in this diff