Эх сурвалжийг харах

Adds a bunch of dedicated EPath parse functions and types

CapXilinx 9 жил өмнө
parent
commit
b956840f25

+ 63 - 0
source/src/cip/cipelectronickey.c

@@ -0,0 +1,63 @@
+ /*******************************************************************************
+ * Copyright (c) 2016, Rockwell Automation, Inc.
+ * All rights reserved.
+ *
+ ******************************************************************************/
+
+#include "cipelectronickey.h"
+
+typedef struct electronic_key_format_4 {
+  CipUint vendor_id;
+  CipUint device_type;
+  CipUint product_code;
+  CipByte major_revision_compatibility;
+  CipUsint minor_revision;
+} ElectronicKeyFormat4;
+
+void SetElectronicKeyFormat4VendorId(const CipUint vendor_id, ElectronicKeyFormat4 *const electronic_key) {
+  electronic_key->vendor_id = vendor_id;
+}
+
+CipUint GetElectronicKeyFormat4VendorId(const ElectronicKeyFormat4 *const electronic_key) {
+  return electronic_key->vendor_id;
+}
+
+void SetElectronicKeyFormat4DeviceType(CipUint device_type, ElectronicKeyFormat4 *const electronic_key) {
+  electronic_key->device_type = device_type;
+}
+
+CipUint GetElectronicKeyFormat4DeviceType(const ElectronicKeyFormat4 *const electronic_key) {
+  return electronic_key->device_type;
+}
+
+void SetElectronicKeyFormat4ProductCode(CipUint product_code, ElectronicKeyFormat4 *const electronic_key) {
+  electronic_key->product_code = product_code;
+}
+
+CipUint GetElectronicKeyFormat4ProductCode(const ElectronicKeyFormat4 *const electronic_key) {
+  return electronic_key->product_code;
+}
+
+void SetElectronicKeyFormat4MajorRevisionCompatibility(CipByte major_revision_compatibility, ElectronicKeyFormat4 *const electronic_key) {
+  electronic_key->major_revision_compatibility = major_revision_compatibility;
+}
+
+CipByte GetElectronicKeyFormat4MajorRevision(const ElectronicKeyFormat4 *const electronic_key) {
+  const CipByte kMajorRevisionMask = 0x7F;
+  return (electronic_key->major_revision_compatibility & kMajorRevisionMask);
+}
+
+bool GetElectronicKeyFormat4Compatibility(const ElectronicKeyFormat4 *const electronic_key) {
+  const CipByte kCompatibilityMask = 0x80;
+  if(kCompatibilityMask == (electronic_key->major_revision_compatibility & kCompatibilityMask) ) {
+    return true;
+  }
+  return false;
+}
+
+void SetElectronicKeyFormat4MinorRevision(CipUsint minor_revision, ElectronicKeyFormat4 *const electronic_key) {
+  electronic_key->minor_revision = minor_revision;
+}
+CipUsint GetElectronicKeyFormat4MinorRevision(const ElectronicKeyFormat4 *const electronic_key) {
+  return electronic_key->minor_revision;
+}

+ 32 - 0
source/src/cip/cipelectronickey.h

@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2016, Rockwell Automation, Inc.
+ * All rights reserved.
+ *
+ ******************************************************************************/
+
+#ifndef SRC_CIP_CIPELECTRONICKEY_H_
+#define SRC_CIP_CIPELECTRONICKEY_H_
+
+#include <stdbool.h>
+
+typedef struct electronic_key_format_4 ElectronicKeyFormat4;
+
+void SetElectronicKeyFormat4VendorId(const CipUint vendor_id, ElectronicKeyFormat4 *const electronic_key);
+CipUint GetElectronicKeyFormat4VendorId(const ElectronicKeyFormat4 *const electronic_key);
+
+void SetElectronicKeyFormat4DeviceType(CipUint device_type, ElectronicKeyFormat4 *const electronic_key);
+CipUint GetElectronicKeyFormat4DeviceType(const ElectronicKeyFormat4 *const electronic_key);
+
+void SetElectronicKeyFormat4ProductCode(CipUint product_code, ElectronicKeyFormat4 *const electronic_key);
+CipUint GetElectronicKeyFormat4ProductCode(const ElectronicKeyFormat4 *const electronic_key);
+
+void SetElectronicKeyFormat4MajorRevisionCompatibility(CipByte major_revision_compatibility, ElectronicKeyFormat4 *const electronic_key);
+//CipByte GetElectronicKeyFormat4MajorRevisionCompatibility(const ElectronicKeyFormat4 *const electronic_key);
+
+CipByte GetElectronicKeyFormat4MajorRevision(const ElectronicKeyFormat4 *const electronic_key);
+bool GetElectronicKeyFormat4Compatibility(const ElectronicKeyFormat4 *const electronic_key);
+
+void SetElectronicKeyFormat4MinorRevision(CipUsint minor_revision, ElectronicKeyFormat4 *const electronic_key);
+CipUsint GetElectronicKeyFormat4MinorRevision(const ElectronicKeyFormat4 *const electronic_key);
+
+#endif /* SRC_CIP_CIPELECTRONICKEY_H_ */

+ 355 - 45
source/src/cip/cipepath.c

@@ -8,44 +8,143 @@
 
 #include "cipepath.h"
 
-const unsigned int kPathSegmentExtendedPort = 15;
+#include "endianconv.h"
+#include "cipelectronickey.h"
+
+const unsigned int kPortSegmentExtendedPort = 15; /**< Reserved port segment port value, indicating the use of the extended port field */
+
+/* Segments */
+const unsigned int kSegmentTypePortSegmentMessageValue = 0x00; /**< Message value of the Port segment */
+const unsigned int kSegmentTypeLogicalSegmentMessageValue = 0x20; /**< Message value of the Logical segment */
+const unsigned int kSegmentTypeNetworkSegmentMessageValue = 0x40; /**< Message value of the Network segment */
+const unsigned int kSegmentTypeSymbolicSegmentMessageValue = 0x60; /**< Message value of the Symbolic segment */
+const unsigned int kSegmentTypeDataSegmentMessageValue = 0x80; /**< Message value of the Data segment */
+const unsigned int kSegmentTypeDataTypeConstructedMessageValue = 0xA0; /**< Message value of the Data type constructed */
+const unsigned int kSegmentTypeDataTypeElementaryMessageValue = 0xC0; /**< Message value of the Data type elementary */
+const unsigned int kSegmentTypeSegmentTypeReservedMessageValue = 0xE0; /**< Reserved value */
+
+const unsigned int kLogicalSegmentLogicalTypeClassIdMessageValue = 0x00; /**< Message value of the logical segment/logical type Class ID */
+const unsigned int kLogicalSegmentLogicalTypeInstanceIdMessageValue = 0x04; /**< Message value of the logical segment/logical type Instance ID */
+const unsigned int kLogicalSegmentLogicalTypeMemberIdMessageValue = 0x08; /**< Message value of the logical segment/logical type Member ID */
+const unsigned int kLogicalSegmentLogicalTypeConnectionPointMessageValue = 0x0C; /**< Message value of the logical segment/logical type Connection Point */
+const unsigned int kLogicalSegmentLogicalTypeAttributeIdMessageValue = 0x10; /**< Message value of the logical segment/logical type Attribute ID */
+const unsigned int kLogicalSegmentLogicalTypeSpecialMessageValue = 0x14; /**< Message value of the logical segment/logical type Special */
+const unsigned int kLogicalSegmentLogicalTypeServiceIdMessageValue = 0x18; /**< Message value of the logical segment/logical type Service ID */
+const unsigned int kLogicalSegmentLogicalTypeExtendedLogicalMessageValue = 0x1C; /**< Message value of the logical segment/logical type Extended Logical */
+
+const unsigned int kLogicalSegmentLogicalFormatEightBitMessageValue = 0x00;
+const unsigned int kLogicalSegmentLogicalFormatSixteenBitMessageValue = 0x01;
+const unsigned int kLogicalSegmentLogicalFormatThirtyTwoBitMessageValue = 0x02;
+
+const unsigned int kLogicalSegmentLogicalExtendedTypeReservedMessageValue = 0x00;
+const unsigned int kLogicalSegmentLogicalExtendedTypeArrayIndexMessageValue = 0x01;
+const unsigned int kLogicalSegmentLogicalExtendedTypeIndirectArrayIndexMessageValue = 0x02;
+const unsigned int kLogicalSegmentLogicalExtendedTypeBitIndexMessageValue = 0x03;
+const unsigned int kLogicalSegmentLogicalExtendedTypeIndirectBitIndexMessageValue = 0x04;
+const unsigned int kLogicalSegmentLogicalExtendedTypeStructureMemberNumberMessageValue = 0x05;
+const unsigned int kLogicalSegmentLogicalExtendedTypeStructureMemberHandleMessageValue = 0x06;
+
+const unsigned int kLogicalSegmentSpecialTypeLogicalFormatElectronicKeyMessageValue = 0x00;
+
+const unsigned int kNetworkSegmentSubtypeScheduleSegmentMessageValue = 0x01;
+const unsigned int kNetworkSegmentSubtypeFixedTagSegmentMessageValue = 0x02;
+const unsigned int kNetworkSegmentSubtypeProductionInhibitTimeInMillisecondsMessageValue = 0x03;
+const unsigned int kNetworkSegmentSubtypeSafetySegmentMessageValue = 0x04;
+const unsigned int kNetworkSegmentSubtypeProductionInhibitTimeInMicrosecondsMessageValue = 0x10;
+const unsigned int kNetworkSegmentSubtypeExtendedNetworkSegmentMessageValue = 0x1F;
+
+typedef enum {
+  kElectronicKeySegmentFormatReserved,
+  kElectronicKeySegmentFormatKeyFormat4
+} ElectronicKeySegmentFormat;
+
+const unsigned int kElectronicKeySegmentFormatKeyFormat4MessageValue = 0x04;
+
+typedef enum {
+  kDataSegmentSubtypeReserved,
+  kDataSegmentSubtypeSimpleData,
+  kDataSegmentSubtypeANSIExtendedSymbol
+} DataSegmentSubtype;
+
+const unsigned int kDataSegmentSubtypeSimpleDataMessageValue = 0x00;
+const unsigned int kDataSegmentSubtypeANSIExtendedSymbolMessageValue = 0x11;
+
+
 
 /*** Path Segment ***/
 SegmentType GetPathSegementType(const char *const cip_path) {
   const unsigned int kSegmentTypeMask = 0xE0;
   const unsigned int segment_type = cip_path & kSegmentTypeMask;
-  switch(segment_type) {
-    case 0x0: return kSegmentTypePortSegment;
-    case 0x20: return kSegmentTypeLogicalSegment;
-    case 0x40: return kSegmentTypeNetworkSegment;
-    case 0x60: return kSegmentTypeSymbolicSegment;
-    case 0x80: return kSegmentTypeDataSegment;
-    case 0xA0: return kSegmentTypeDataTypeConstructed;
-    case 0xC0: return kSegmentTypeDataTypeElementary;
-    case 0xE0: return kSegmentTypeSegmentTypeReserved;
+  SegmentType result = kSegmentTypeSegmentTypeReserved;
+  switch (segment_type) {
+    case kSegmentTypePortSegmentMessageValue:
+      result = kSegmentTypePortSegment;
+      break;
+    case kSegmentTypeLogicalSegmentMessageValue:
+      result = kSegmentTypeLogicalSegment;
+      break;
+    case kSegmentTypeNetworkSegmentMessageValue:
+      result = kSegmentTypeNetworkSegment;
+      break;
+    case kSegmentTypeSymbolicSegmentMessageValue:
+      result = kSegmentTypeSymbolicSegment;
+      break;
+    case kSegmentTypeDataSegmentMessageValue:
+      result = kSegmentTypeDataSegment;
+      break;
+    case kSegmentTypeDataTypeConstructedMessageValue:
+      result = kSegmentTypeDataTypeConstructed;
+      break;
+    case kSegmentTypeDataTypeElementaryMessageValue:
+      result = kSegmentTypeDataTypeElementary;
+      break;
+    case kSegmentTypeSegmentTypeReservedMessageValue:
+      result = kSegmentTypeSegmentTypeReserved;
+      break;
+    default:
+      OPENER_ASSERT(
+          "Invalid Segment type in the message! We should never come here!\n");
+      break;
   }
-  OPENER_ASSERT("Invalid Segment type in the message! We should never come here!\n");
-  return kSegmentTypeSegmentTypeReserved;
+  return result;
 }
 
 void SetPathSegementType(SegmentType segment_type, char *const cip_path) {
   switch (segment_type) {
-    case kSegmentTypePortSegment: cip_path |= 0x00; break;
-    case kSegmentTypeLogicalSegment: cip_path |= 0x20; break;
-    case kSegmentTypeNetworkSegment: cip_path |= 0x40; break;
-    case kSegmentTypeSymbolicSegment: cip_path |= 0x60; break;
-    case kSegmentTypeDataSegment: cip_path |= 0x80; break;
-    case kSegmentTypeDataTypeConstructed: cip_path |= 0xA0; break;
-    case kSegmentTypeDataTypeElementary: cip_path |= 0xC0; break;
-    case kSegmentTypeSegmentTypeReserved: cip_path |= 0xE0; break;
-    default: OPENER_ASSERT("Invalid Segment type chosen! We should never come here!\n");
+    case kSegmentTypePortSegment:
+      cip_path |= kSegmentTypePortSegmentMessageValue;
+      break;
+    case kSegmentTypeLogicalSegment:
+      cip_path |= kSegmentTypeLogicalSegmentMessageValue;
+      break;
+    case kSegmentTypeNetworkSegment:
+      cip_path |= kSegmentTypeNetworkSegmentMessageValue;
+      break;
+    case kSegmentTypeSymbolicSegment:
+      cip_path |= kSegmentTypeSymbolicSegmentMessageValue;
+      break;
+    case kSegmentTypeDataSegment:
+      cip_path |= kSegmentTypeDataSegmentMessageValue;
+      break;
+    case kSegmentTypeDataTypeConstructed:
+      cip_path |= kSegmentTypeDataTypeConstructedMessageValue;
+      break;
+    case kSegmentTypeDataTypeElementary:
+      cip_path |= kSegmentTypeDataTypeElementaryMessageValue;
+      break;
+    case kSegmentTypeSegmentTypeReserved:
+      cip_path |= kSegmentTypeSegmentTypeReservedMessageValue;
+      break;
+    default:
+      OPENER_ASSERT(
+          "Invalid Segment type chosen! We should never come here!\n");
   }
 }
 
 /*** Port Segment ***/
 bool GetPathPortSegementExtendedLinkAddressSizeBit(const char *const cip_path) {
   const unsigned int kExtendedLinkAddressSizeMask = 0x10;
-  if(kExtendedLinkAddressSizeMask == cip_path & kExtendedLinkAddressSizeMask) {
+  if (kExtendedLinkAddressSizeMask == cip_path & kExtendedLinkAddressSizeMask) {
     return true;
   }
   return false;
@@ -58,48 +157,259 @@ unsigned int GetPathPortSegmentPortIdentifier(const char *const cip_path) {
   return port_identifier;
 }
 
-void SetPathPortSegmentPortIdentifier(const unsigned int port_identifier, char *const cip_path) {
-  OPENER_ASSERT(port_identifier < 16, "Port identifier too large for standard port identifier field\n");
+void SetPathPortSegmentPortIdentifier(const unsigned int port_identifier,
+                                      char *const cip_path) {
+  OPENER_ASSERT(
+      port_identifier < 16,
+      "Port identifier too large for standard port identifier field\n");
 
 }
 
 unsigned int GetPathPortSegementLinkAddressSize(const char *const cip_path) {
-  OPENER_ASSERT(false == GetPathPortSegementExtendedLinkAddressSizeBit(cip_path), "Call to non existent extended link address size\n");
+  OPENER_ASSERT(
+  false == GetPathPortSegementExtendedLinkAddressSizeBit(cip_path),
+                "Call to non existent extended link address size\n");
   return *(cip_path + 1);
 }
 
 unsigned int GetPathPortSegmentExtendedPortNumber(const char *const cip_path) {
-  OPENER_ASSERT(kPathSegmentExtendedPort == GetPathPortSegmentPortIdentifier, "There is no extended port available!\n");
-  const unsigned int kExtendedPortSegmentPosition = GetPathPortSegementExtendedLinkAddressSizeBit(cip_path) == true ? 3 : 2;
-  return cip_path[kExtendedPortSegmentPosition] + (cip_path[kExtendedPortSegmentPosition + 1] << 8);
+  OPENER_ASSERT(kPortSegmentExtendedPort == GetPathPortSegmentPortIdentifier,
+                "There is no extended port available!\n");
+  const unsigned int kExtendedPortSegmentPosition =
+      GetPathPortSegementExtendedLinkAddressSizeBit(cip_path) == true ? 3 : 2;
+  return cip_path[kExtendedPortSegmentPosition]
+      + (cip_path[kExtendedPortSegmentPosition + 1] << 8);
 }
 
-void SetPathPortSegmentExtendedPortIdentifier(const unsigned int extended_port_identifier, char *const cip_path) {
-  SetPathPortSegmentPortIdentifier(kPathSegmentExtendedPort, cip_path);
-  const unsigned int kExtendedPortSegmentPosition = GetPathPortSegementExtendedLinkAddressSizeBit(cip_path) == true ? 3 : 2;
-  cip_path[kExtendedPortSegmentPosition] = (char*)(extended_port_identifier & 0x00FF);
-  cip_path[kExtendedPortSegmentPosition + 1] = (char*)((extended_port_identifier & 0xFF00) >> 8);
+void SetPathPortSegmentExtendedPortIdentifier(
+    const unsigned int extended_port_identifier, char *const cip_path) {
+  SetPathPortSegmentPortIdentifier(kPortSegmentExtendedPort, cip_path);
+  const unsigned int kExtendedPortSegmentPosition =
+      GetPathPortSegementExtendedLinkAddressSizeBit(cip_path) == true ? 3 : 2;
+  cip_path[kExtendedPortSegmentPosition] = (char*) (extended_port_identifier
+      & 0x00FF);
+  cip_path[kExtendedPortSegmentPosition + 1] =
+      (char*) ((extended_port_identifier & 0xFF00) >> 8);
 }
 /*** Port Segment ***/
 
 /*** Logical Segment ***/
 
-LogicalSegmentLogicalType GetPathLogicalSegmentLogicalType(const char *const cip_path) {
+LogicalSegmentLogicalType GetPathLogicalSegmentLogicalType(
+    const char *const cip_path) {
   const unsigned int kLogicalTypeMask = 0x1C;
-  const unsigned int logical_type = cip_path & kLogicalTypeMask;
+  const unsigned int logical_type = (*cip_path) & kLogicalTypeMask;
   LogicalSegmentLogicalType result = kLogicalSegmentLogicalTypeExtendedLogical;
-  switch(logical_type) {
-    case 0x00: result = kLogicalSegmentLogicalTypeClassId; break;
-    case 0x04: result = kLogicalSegmentLogicalTypeInstanceId; break;
-    case 0x08: result = kLogicalSegmentLogicalTypeMemberId; break;
-    case 0x0C: result = kLogicalSegmentLogicalTypeConnectionPoint; break;
-    case 0x10: result = kLogicalSegmentLogicalTypeAttributeId; break;
-    case 0x14: result = kLogicalSegmentLogicalTypeSpecial; break;
-    case 0x18: result = kLogicalSegmentLogicalTypeServiceId; break;
-    case 0x1C: result = kLogicalSegmentLogicalTypeExtendedLogical; break;
-    default: OPENER_ASSERT("It is not possible to reach this point"); break;
+  switch (logical_type) {
+    case kLogicalSegmentLogicalTypeClassIdMessageValue:
+      result = kLogicalSegmentLogicalTypeClassId;
+      break;
+    case kLogicalSegmentLogicalTypeInstanceIdMessageValue:
+      result = kLogicalSegmentLogicalTypeInstanceId;
+      break;
+    case kLogicalSegmentLogicalTypeMemberIdMessageValue:
+      result = kLogicalSegmentLogicalTypeMemberId;
+      break;
+    case kLogicalSegmentLogicalTypeConnectionPointMessageValue:
+      result = kLogicalSegmentLogicalTypeConnectionPoint;
+      break;
+    case kLogicalSegmentLogicalTypeAttributeIdMessageValue:
+      result = kLogicalSegmentLogicalTypeAttributeId;
+      break;
+    case kLogicalSegmentLogicalTypeSpecialMessageValue:
+      result = kLogicalSegmentLogicalTypeSpecial;
+      break;
+    case kLogicalSegmentLogicalTypeServiceIdMessageValue:
+      result = kLogicalSegmentLogicalTypeServiceId;
+      break;
+    case kLogicalSegmentLogicalTypeExtendedLogicalMessageValue:
+      result = kLogicalSegmentLogicalTypeExtendedLogical;
+      break;
+    default:
+      OPENER_ASSERT(
+          "Logical segment/logical type: It is not possible to reach this point!\n");
+      break;
   }
   return result;
 }
 
+LogicalSegmentLogicalFormat GetPathLogicalSegmentLogicalFormat(
+    const char *const cip_path) {
+  const unsigned int kLogicalFormatMask = 0x03;
+  const unsigned int logical_format = (*cip_path) & kLogicalFormatMask;
+  LogicalSegmentLogicalFormat result = kLogicalSegmentLogicalFormatEightBit;
+  switch (logical_format) {
+    case kLogicalSegmentLogicalFormatEightBitMessageValue:
+      result = kLogicalSegmentLogicalFormatEightBit;
+      break;
+    case kLogicalSegmentLogicalFormatSixteenBitMessageValue:
+      result = kLogicalSegmentLogicalFormatSixteenBit;
+      break;
+    case kLogicalSegmentLogicalFormatThirtyTwoBitMessageValue:
+      result = kLogicalSegmentLogicalFormatThirtyTwoBit;
+      break;
+    default:
+      OPENER_ASSERT(
+          "Logical segment/logical type: Invalid logical type detected!\n");
+      break;
+  }
+  return result;
+}
+
+LogicalSegmentExtendedLogicalType GetPathLogicalSegmentExtendedLogicalType(const char *const cip_path) {
+  OPENER_ASSERT(kLogicalSegmentLogicalTypeExtendedLogicalMessageValue == GetPathLogicalSegmentLogicalType(cip_path),
+                "Trying to extract non-existent extended logical type");
+  const char extended_logical_type = *(cip_path + 1);
+  LogicalSegmentExtendedLogicalType result = kLogicalSegmentExtendedLogicalTypeReserved;
+  switch(extended_logical_type) {
+    case kLogicalSegmentLogicalExtendedTypeArrayIndexMessageValue: result = kLogicalSegmentExtendedLogicalTypeArrayIndex; break;
+    case kLogicalSegmentLogicalExtendedTypeIndirectArrayIndexMessageValue: result = kLogicalSegmentExtendedLogicalTypeIndirectArrayIndex; break;
+    case kLogicalSegmentLogicalExtendedTypeBitIndexMessageValue: result = kLogicalSegmentExtendedLogicalTypeBitIndex; break;
+    case kLogicalSegmentLogicalExtendedTypeIndirectBitIndexMessageValue: result = kLogicalSegmentExtendedLogicalTypeIndirectBitIndex; break;
+    case kLogicalSegmentLogicalExtendedTypeStructureMemberNumberMessageValue: result = kLogicalSegmentExtendedLogicalTypeStructureMemberNumber; break;
+    case kLogicalSegmentLogicalExtendedTypeStructureMemberHandleMessageValue: result = kLogicalSegmentExtendedLogicalTypeStructureMemberHandle; break;
+    default: result = kLogicalSegmentExtendedLogicalTypeReserved;
+  }
+  return result;
+}
+
+LogicalSegmentSpecialTypeLogicalFormat GetPathLogicalSegmentSpecialTypeLogicalType(const char *const cip_path) {
+  OPENER_ASSERT(kSegmentTypeLogicalSegment == GetPathSegementType(cip_path), "Not a logical segment!\n");
+  const unsigned int kLogicalFormatMask = 0x03;
+  const unsigned int logical_format = (*cip_path) & kLogicalFormatMask;
+
+  LogicalSegmentSpecialTypeLogicalFormat result = kLogicalSegmentSpecialTypeLogicalFormatReserved;
+  switch(logical_format) {
+    case kLogicalSegmentSpecialTypeLogicalFormatElectronicKeyMessageValue:
+      result = kLogicalSegmentSpecialTypeLogicalFormatElectronicKey; break;
+    default: result = kLogicalSegmentSpecialTypeLogicalFormatReserved; break;
+  }
+
+  return result;
+}
+
+ElectronicKeySegmentFormat *GetPathLogicalSegmentElectronicKeyFormat(const char *const cip_path) {
+  OPENER_ASSERT(kLogicalSegmentSpecialTypeLogicalFormatElectronicKey ==
+      GetPathLogicalSegmentSpecialTypeLogicalType(cip_path), "Not an electronic key!\n");
+  ElectronicKeySegmentFormat result = kElectronicKeySegmentFormatReserved;
+  switch(*(cip_path + 1)) {
+    case kElectronicKeySegmentFormatKeyFormat4MessageValue: result = kElectronicKeySegmentFormatKeyFormat4; break;
+    default: result = kElectronicKeySegmentFormatReserved; break;
+  }
+  return result;
+}
+
+ElectronicKeyFormat4 *GetPathLogicalSegmentElectronicKeyFormat4(const char *const cip_path) {
+  OPENER_ASSERT(kElectronicKeySegmentFormatKeyFormat4 ==
+      GetPathLogicalSegmentElectronicKeyFormat(cip_path), "Not electronic key format 4!\n");
+
+  const char *message_runner = (const char *)cip_path;
+  ElectronicKeyFormat4 *result = calloc(sizeof(ElectronicKeySegmentFormat));
+  SetElectronicKeyFormat4VendorId(GetIntFromMessage(&message_runner), result);
+  SetElectronicKeyFormat4DeviceType(GetIntFromMessage(&message_runner), result);
+  SetElectronicKeyFormat4ProductCode(GetIntFromMessage(&message_runner), result);
+  SetElectronicKeyFormat4MajorRevisionCompatibility(GetSintFromMessage(&message_runner), result);
+  SetElectronicKeyFormat4MinorRevision(GetSIntFromMessage(&message_runner), result);
+
+  return result;
+}
+
 /*** Logical Segment ***/
+
+
+/*** Network Segment ***/
+
+/** @brief Return the Network Segment subtype
+ *
+ *  @param cip_path Pointer to the start of the EPath message
+ *  @return The Network Segment subtype of the EPath
+ */
+NetworkSegmentSubType GetPathNetworkSegmentSubtype(const char *const cip_path) {
+  const unsigned int kSubtypeMask = 0x1F;
+  const unsigned int subtype = (*cip_path) & kSubtypeMask;
+  NetworkSegmentSubType result = kNetworkSegmentSubtypeReserved;
+  switch(subtype) {
+    case kNetworkSegmentSubtypeScheduleSegmentMessageValue:
+      result = kNetworkSegmentSubtypeScheduleSegment; break;
+    case kNetworkSegmentSubtypeFixedTagSegmentMessageValue:
+      result = kNetworkSegmentSubtypeFixedTagSegment; break;
+    case kNetworkSegmentSubtypeProductionInhibitTimeInMillisecondsMessageValue:
+      result = kNetworkSegmentSubtypeProductionInhibitTimeInMilliseconds; break;
+    case kNetworkSegmentSubtypeSafetySegmentMessageValue:
+      result = kNetworkSegmentSubtypeSafetySegment; break;
+    case kNetworkSegmentSubtypeProductionInhibitTimeInMicrosecondsMessageValue:
+      result = kNetworkSegmentSubtypeProductionInhibitTimeInMicroseconds; break;
+    default: result = kNetworkSegmentSubtypeReserved; break;
+  }
+
+  return result;
+}
+
+/**
+ * @brief Return the Production Inhibit Time in milliseconds from an EPath
+ *
+ * @param cip_path Pointer to the start of the EPath message
+ * @return the Production Inhibit Time in milliseconds ranging from 0 to 255
+ */
+CipUsint GetPathNetworkSegmentProductionInhibitTimeInMilliseconds(const char *const cip_path) {
+  OPENER_ASSERT(kSegmentTypeNetworkSegment == GetPathSegementType(cip_path),"Not a network segment!\n");
+  OPENER_ASSERT(kNetworkSegmentSubtypeProductionInhibitTimeInMilliseconds == GetPathNetworkSegmentSubtype(cip_path),
+                "Not a Production Inhibit Time milliseconds segment!\n");
+  return *(cip_path + 1);
+}
+
+/**
+ * @brief Return the Production Inhibit Time in microseconds from an EPath
+ *
+ * @param cip_path Pointer to the start of the EPath message
+ * @return the Production Inhibit Time in microseconds ranging from 0 to 4294967295
+ */
+CipUdint GetPathNetworkSegmentProductionInhibitTimeInMicroseconds(const char *const cip_path) {
+  OPENER_ASSERT(kSegmentTypeNetworkSegment == GetPathSegementType(cip_path),"Not a network segment!\n");
+  OPENER_ASSERT(kNetworkSegmentSubtypeProductionInhibitTimeInMicroseconds == GetPathNetworkSegmentSubtype(cip_path),
+                  "Not a Production Inhibit Time microseconds segment!\n");
+  OPENER_ASSERT(2 == *(cip_path + 1), "Data Words length is incorrect! See CIP Spec Vol.1 C-1.4.3.3.2\n");
+  const char *message_runner = cip_path;
+  return GetDintFromMessage(&message_runner);
+}
+
+/*** Network Segment ***/
+
+/*** Symbolic Segment ***/
+
+/* Currently not supported */
+
+/*** Symbolic Segment ***/
+
+/*** Data Segment ***/
+
+DataSegmentSubtype GetPathDataSegmentSubtype(const char *const cip_path) {
+  const unsigned int kDataSegmentSubtypeMask = 0x1F;
+  const unsigned int data_subtype = (*cip_path) & kDataSegmentSubtypeMask;
+
+  DataSegmentSubtype result = kDataSegmentSubtypeReserved;
+  switch(data_subtype) {
+    case kDataSegmentSubtypeSimpleDataMessageValue:
+      result = kDataSegmentSubtypeSimpleData; break;
+    case kDataSegmentSubtypeANSIExtendedSymbolMessageValue:
+      result = kDataSegmentSubtypeANSIExtendedSymbol; break;
+    default: result = kDataSegmentSubtypeReserved; break;
+  }
+  return result;
+}
+
+/** @brief Returns the amount of 16-bit data words in the Simple Data EPath
+ *
+ * @param cip_path Pointer to the start of the EPath message
+ * @return The amount of 16-bit words of data in the EPath
+ */
+CipUsint GetPathDataSegmentSimpleDataWordLength(const char *const cip_path) {
+  OPENER_ASSERT(kSegmentTypeDataSegment == GetPathSegementType(cip_path),"Not a data segment!\n");
+  OPENER_ASSERT(kDataSegmentSubtypeSimpleData == GetPathDataSegmentSubtype(cip_path), "Not a simple data segment!\n");
+
+  const char *message_runner = cip_path;
+  return GetSintFromMessage(&message_runner);
+}
+
+/*** Data Segment ***/
+

+ 10 - 0
source/src/cip/cipepath.h

@@ -11,6 +11,16 @@
 
 #include "ciptypes.h"
 
+typedef enum {
+  kNetworkSegmentSubtypeReserved,
+  kNetworkSegmentSubtypeScheduleSegment,
+  kNetworkSegmentSubtypeFixedTagSegment,
+  kNetworkSegmentSubtypeProductionInhibitTimeInMilliseconds,
+  kNetworkSegmentSubtypeSafetySegment,
+  kNetworkSegmentSubtypeProductionInhibitTimeInMicroseconds,
+  kNetworkSegmentSubtypeExtendedNetworkSegment
+} NetworkSegmentSubtype;
+
 SegmentType GetPathSegementType(const char *const cip_path);
 
 void SetPathSegementType(SegmentType segment_type, char *const cip_path);

+ 34 - 19
source/src/cip/ciptypes.h

@@ -15,14 +15,14 @@
  */
 typedef enum {
   /* Segments */
-  kSegmentTypePortSegment = 0x00, /**< Port segment */
-  kSegmentTypeLogicalSegment = 0x20, /**< Logical segment */
-  kSegmentTypeNetworkSegment = 0x40, /**< Network segment */
-  kSegmentTypeSymbolicSegment = 0x60, /**< Symbolic segment */
-  kSegmentTypeDataSegment = 0x80, /**< Data segment */
-  kSegmentTypeDataTypeConstructed = 0xA0, /**< Data type constructed */
-  kSegmentTypeDataTypeElementary = 0xC0, /**< Data type elementary */
-  kSegmentTypeSegmentTypeReserved = 0xE0
+  kSegmentTypePortSegment, /**< Port segment */
+  kSegmentTypeLogicalSegment, /**< Logical segment */
+  kSegmentTypeNetworkSegment, /**< Network segment */
+  kSegmentTypeSymbolicSegment, /**< Symbolic segment */
+  kSegmentTypeDataSegment, /**< Data segment */
+  kSegmentTypeDataTypeConstructed, /**< Data type constructed */
+  kSegmentTypeDataTypeElementary, /**< Data type elementary */
+  kSegmentTypeSegmentTypeReserved
 } SegmentType;
 
 /** @brief Port Segment flags */
@@ -32,24 +32,39 @@ typedef enum {
 
 /** @brief Enum containing values which kind of logical segment is encoded */
 typedef enum {
-  kLogicalSegmentLogicalTypeClassId = 0x00, /**< Class ID */
-  kLogicalSegmentLogicalTypeInstanceId = 0x04, /**< Instance ID */
-  kLogicalSegmentLogicalTypeMemberId = 0x08, /**< Member ID */
-  kLogicalSegmentLogicalTypeConnectionPoint = 0x0C, /**< Connection Point */
-  kLogicalSegmentLogicalTypeAttributeId = 0x10, /**< Attribute ID */
-  kLogicalSegmentLogicalTypeSpecial = 0x14, /**< Special */
-  kLogicalSegmentLogicalTypeServiceId = 0x18, /**< Service ID */
-  kLogicalSegmentLogicalTypeExtendedLogical = 0x1C /**< Extended Logical */
+  kLogicalSegmentLogicalTypeClassId, /**< Class ID */
+  kLogicalSegmentLogicalTypeInstanceId, /**< Instance ID */
+  kLogicalSegmentLogicalTypeMemberId, /**< Member ID */
+  kLogicalSegmentLogicalTypeConnectionPoint, /**< Connection Point */
+  kLogicalSegmentLogicalTypeAttributeId, /**< Attribute ID */
+  kLogicalSegmentLogicalTypeSpecial, /**< Special */
+  kLogicalSegmentLogicalTypeServiceId, /**< Service ID */
+  kLogicalSegmentLogicalTypeExtendedLogical/**< Extended Logical */
 } LogicalSegmentLogicalType;
 
+typedef enum {
+  kLogicalSegmentExtendedLogicalTypeReserved,
+  kLogicalSegmentExtendedLogicalTypeArrayIndex,
+  kLogicalSegmentExtendedLogicalTypeIndirectArrayIndex,
+  kLogicalSegmentExtendedLogicalTypeBitIndex,
+  kLogicalSegmentExtendedLogicalTypeIndirectBitIndex,
+  kLogicalSegmentExtendedLogicalTypeStructureMemberNumber,
+  kLogicalSegmentExtendedLogicalTypeStructureMemberHandle
+} LogicalSegmentExtendedLogicalType;
+
 /** @brief Enum containing values how long the encoded value will be (8, 16, or
  * 32 bit) */
 typedef enum {
-  kLogicalSegmentLogicalFormatEightBitValue = 0x00,
-  kLogicalSegmentLogicalFormatSixteenBitValue = 0x01,
-  kLogicalSegmentLogicalFormatThirtyTwoBitValue = 0x02
+  kLogicalSegmentLogicalFormatEightBit,
+  kLogicalSegmentLogicalFormatSixteenBit,
+  kLogicalSegmentLogicalFormatThirtyTwoBit
 } LogicalSegmentLogicalFormat;
 
+typedef enum {
+  kLogicalSegmentSpecialTypeLogicalFormatReserved,
+  kLogicalSegmentSpecialTypeLogicalFormatElectronicKey
+} LogicalSegmentSpecialTypeLogicalFormat;
+
 typedef enum {
   kProductionTimeInhibitTimeNetworkSegment = 0x43 /**< identifier indicating a production inhibit time network segment */
 } NetworkSegmentSubType;

+ 1 - 1
source/tests/cip/CMakeLists.txt

@@ -1,7 +1,7 @@
 
 opener_common_includes()
 
-set( CipTestSrc connectionmanagertest.cpp )
+set( CipTestSrc connectionmanagertest.cpp cipepathtest.cpp )
 
 include_directories( ${SRC_DIR}/cip )
 

+ 19 - 0
source/tests/cip/cipelectronickey.cpp

@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2009, Rockwell Automation, Inc.
+ * All rights reserved.
+ *
+ ******************************************************************************/
+
+#include <CppUTest/TestHarness.h>
+#include <stdint.h>
+#include <string.h>
+
+extern "C" {
+
+#include "cipelectronickey.h"
+
+}
+
+TEST_GROUP(CipElectronicKey) {
+
+};

+ 19 - 0
source/tests/cip/cipepathtest.cpp

@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2009, Rockwell Automation, Inc.
+ * All rights reserved.
+ *
+ ******************************************************************************/
+
+#include <CppUTest/TestHarness.h>
+#include <stdint.h>
+#include <string.h>
+
+extern "C" {
+
+#include "cipepath.h"
+
+}
+
+TEST_GROUP(CipEpath) {
+
+};