|
@@ -0,0 +1,936 @@
|
|
|
+/*------------------------------------------------------------------------*/
|
|
|
+/* Copyright (C) SIEMENS CORP., 2018 All rights reserved.*/
|
|
|
+/* All rights reserved. */
|
|
|
+/* Redistribution and use in source and binary forms, with or without */
|
|
|
+/* modification, are permitted provided that the following conditions */
|
|
|
+/* are met: */
|
|
|
+/* 1. Redistributions of source code must retain the above copyright */
|
|
|
+/* notice, this list of conditions and the following disclaimer. */
|
|
|
+/* 2. Redistributions in binary form must reproduce the above copyright */
|
|
|
+/* notice, this list of conditions and the following disclaimer in the */
|
|
|
+/* documentation and/or other materials provided with the distribution. */
|
|
|
+/* 3. Neither the name of the copyright holder nor the names of its */
|
|
|
+/* contributors may be used to endorse or promote products derived from */
|
|
|
+/* this software without specific prior written permission. */
|
|
|
+/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
|
|
|
+/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
|
|
|
+/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
|
|
|
+/* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE */
|
|
|
+/* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */
|
|
|
+/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */
|
|
|
+/* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS */
|
|
|
+/* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) */
|
|
|
+/* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, */
|
|
|
+/* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING */
|
|
|
+/* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
|
|
|
+/* POSSIBILITY OF SUCH DAMAGE. */
|
|
|
+/*------------------------------------------------------------------------*/
|
|
|
+/*------------------------------------------------------------------------*/
|
|
|
+/* Attention : Callbacks are running concurrent in other threads so all */
|
|
|
+/* printf statements should be synchronized. But this sample */
|
|
|
+/* application doesn't synchronize for simplicity ! */
|
|
|
+/*------------------------------------------------------------------------*/
|
|
|
+
|
|
|
+#include "im.h"
|
|
|
+#include "dev_certify_energy.h"
|
|
|
+
|
|
|
+#ifdef WIN32
|
|
|
+#include <windows.h>
|
|
|
+#include <stdio.h>
|
|
|
+#include <conio.h>
|
|
|
+#else
|
|
|
+#define _BSD_SOURCE /* for usleep */
|
|
|
+#include <stdio.h>
|
|
|
+#include <unistd.h>
|
|
|
+#include <stdlib.h>
|
|
|
+#include <poll.h>
|
|
|
+#include <termios.h>
|
|
|
+#include <string.h>
|
|
|
+#include <time.h>
|
|
|
+#define Sleep(x) usleep(x*1000)
|
|
|
+#endif
|
|
|
+
|
|
|
+#include "servusrx.h"
|
|
|
+
|
|
|
+/*----------------------------------------------------------------------------------------------------*/
|
|
|
+/* DEFINES */
|
|
|
+/*----------------------------------------------------------------------------------------------------*/
|
|
|
+
|
|
|
+#define STRNCMP_EQUAL 0
|
|
|
+#define LINE_LENGTH_MAX 255 /* Maximum line length of persistent im data file */
|
|
|
+#define NUMOF_PERSISTENT_IM_ITEMS 6 /* persistent: IM_Revision_Counter, IM_Tag_Function, IM_Tag_Location, IM_Date, IM_Descriptor, IM_Signature */
|
|
|
+
|
|
|
+#define LEN_IM_ORDERID 20
|
|
|
+#define LEN_IM_SERIAL_NUMBER 16
|
|
|
+#define LEN_IM_SOFTWARE_REVISION 4
|
|
|
+#define LEN_IM_TAG_FUNCTION 32
|
|
|
+#define LEN_IM_TAG_LOCATION 22
|
|
|
+#define LEN_IM_DATE 16
|
|
|
+#define LEN_IM_DESCRIPTOR 54
|
|
|
+#define LEN_IM_SIGNATURE 54
|
|
|
+
|
|
|
+/*----------------------------------------------------------------------------------------------------*/
|
|
|
+/* TYPES */
|
|
|
+/*----------------------------------------------------------------------------------------------------*/
|
|
|
+
|
|
|
+typedef struct IM_PERMANENT_tag /*size: 142*/
|
|
|
+{
|
|
|
+ PNIO_UINT16 VendorID;
|
|
|
+ PNIO_UINT16 OrderID;
|
|
|
+ PNIO_UINT8 pIM_Serial_Number[16];
|
|
|
+ PNIO_UINT16 IM_Hardware_Revision;
|
|
|
+ PNIO_UINT8 IM_Software_Revision[4];
|
|
|
+ PNIO_UINT16 IM_Profile_ID;
|
|
|
+ PNIO_UINT16 IM_Profile_Specific_Type;
|
|
|
+ PNIO_UINT16 IM_Version;
|
|
|
+ PNIO_UINT16 IM_Supported;
|
|
|
+ PNIO_UINT8 IM_Tag_Function[32];
|
|
|
+ PNIO_UINT8 IM_Tag_Location[22];
|
|
|
+ PNIO_UINT8 IM_Date[16];
|
|
|
+ PNIO_UINT8 IM_Descriptor[54];
|
|
|
+ PNIO_UINT8 IM_Signature[54];
|
|
|
+} IM_PERMANENT;
|
|
|
+
|
|
|
+typedef struct tag_IM_DATA
|
|
|
+{
|
|
|
+ PNIO_IM0_TYPE im0;
|
|
|
+ PNIO_IM1_TYPE im1;
|
|
|
+ PNIO_IM2_TYPE im2;
|
|
|
+ PNIO_IM3_TYPE im3;
|
|
|
+ PNIO_IM4_TYPE im4;
|
|
|
+} IM_DATA;
|
|
|
+
|
|
|
+typedef enum
|
|
|
+{
|
|
|
+ IM_Revision_Counter = 0,
|
|
|
+ IM_Tag_Function = 1,
|
|
|
+ IM_Tag_Location = 2,
|
|
|
+ IM_Date = 3,
|
|
|
+ IM_Descriptor = 4,
|
|
|
+ IM_Signature = 5
|
|
|
+} IM_PERSISTENT_DATA_e;
|
|
|
+
|
|
|
+typedef enum
|
|
|
+{
|
|
|
+ IM_EQUAL = 0,
|
|
|
+ IM_READ_DIFFER = 1,
|
|
|
+ IM_WRITE_DIFFER = 2,
|
|
|
+ IM_READ_WRITE_DIFFER = 3
|
|
|
+} IM_CMP_E;
|
|
|
+
|
|
|
+typedef struct tag_IM_PERSISTENT_DATA /* persistent IM data */
|
|
|
+{
|
|
|
+ PNIO_UINT16 IM_Revision_Counter;
|
|
|
+ PNIO_UINT8 IM_Tag_Function[LEN_IM_TAG_FUNCTION];
|
|
|
+ PNIO_UINT8 IM_Tag_Location[LEN_IM_TAG_LOCATION];
|
|
|
+ PNIO_UINT8 IM_Date[LEN_IM_DATE];
|
|
|
+ PNIO_UINT8 IM_Descriptor[LEN_IM_DESCRIPTOR];
|
|
|
+ PNIO_UINT8 IM_Signature[LEN_IM_SIGNATURE];
|
|
|
+} IM_PERSISTENT_DATA;
|
|
|
+
|
|
|
+/*----------------------------------------------------------------------------------------------------*/
|
|
|
+/* I&M DATA */
|
|
|
+/*----------------------------------------------------------------------------------------------------*/
|
|
|
+
|
|
|
+static IM_DATA* im_work = 0; /* current IM data */
|
|
|
+static const char* name_IM_PERSISTENT_DATA[] = /* names of persistent IM data items */
|
|
|
+{
|
|
|
+ "IM_Revision_Counter",
|
|
|
+ "IM_Tag_Function",
|
|
|
+ "IM_Tag_Location",
|
|
|
+ "IM_Date",
|
|
|
+ "IM_Descriptor",
|
|
|
+ "IM_Signature"
|
|
|
+};
|
|
|
+
|
|
|
+static const IM_DATA im_default = /* default IM data */
|
|
|
+{
|
|
|
+ { /* I&M0 */
|
|
|
+ {
|
|
|
+ 0x0020, /* BlockHeader.BlockType */
|
|
|
+ 0x0038, /* BlockHeader.BlockLength */
|
|
|
+ 0x01, /* BlockHeader.BlockVersionHigh */
|
|
|
+ 0x00 /* BlockHeader.BlockVersionLow */
|
|
|
+ },
|
|
|
+ 0x00, /* VendorIDHigh - will be set to value from readConfig! */
|
|
|
+ 0x2A, /* VendorIDLow - will be set to value from readConfig! */
|
|
|
+ { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', }, /* OrderID[20] -> will be set to selected device annotation! */
|
|
|
+ { '0', '0', '0', '-', '0', '0', '0', '-', '0', '0', '0', '-', '0', '0', '0', '1' }, /* IM_Serial_Number[16] -> will be set to actual serial number! */
|
|
|
+ 9, /* IM_Hardware_Revision - will be set to selected device annotation! */
|
|
|
+ { 'V', 2, 7, 0 }, /* IM_Software_Revision[4] - will be set to selected device annotation! */
|
|
|
+ 0x0000, /* IM_Revision_Counter */
|
|
|
+ 0x0000, /* IM_Profile_ID -> Generic Device */
|
|
|
+ 0x0003, /* IM_Profile_Specific_Type -> Communication Module -> www.profibus.com/IM/Device_ID_Table_6102.xml */
|
|
|
+ 0x01, /* IM_Version_Major */
|
|
|
+ 0x01, /* IM_Version_Minor */
|
|
|
+ 0x003e /* IM_Supported -> IM0 bis IM4 */
|
|
|
+ },
|
|
|
+ { /* I&M1 */
|
|
|
+ {
|
|
|
+ 0x0021, /* BlockHeader.BlockType */
|
|
|
+ 0x0038, /* BlockHeader.BlockLength */
|
|
|
+ 0x01, /* BlockHeader.BlockVersionHigh */
|
|
|
+ 0x00 /* BlockHeader.BlockVersionLow */
|
|
|
+ },
|
|
|
+ { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }, /* IM_Tag_Function[32] */
|
|
|
+ { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } /* IM_Tag_Location[22] */
|
|
|
+ },
|
|
|
+ { /* I&M2 */
|
|
|
+ {
|
|
|
+ 0x0022, /* BlockHeader.BlockType */
|
|
|
+ 0x0012, /* BlockHeader.BlockLength */
|
|
|
+ 0x01, /* BlockHeader.BlockVersionHigh */
|
|
|
+ 0x00 /* BlockHeader.BlockVersionLow */
|
|
|
+ },
|
|
|
+ { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } /* IM_Date[16] */
|
|
|
+ },
|
|
|
+ { /* I&M3 */
|
|
|
+ {
|
|
|
+ 0x0023, /* BlockHeader.BlockType */
|
|
|
+ 0x0038, /* BlockHeader.BlockLength */
|
|
|
+ 0x01, /* BlockHeader.BlockVersionHigh */
|
|
|
+ 0x00 /* BlockHeader.BlockVersionLow */
|
|
|
+ },
|
|
|
+ { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } /* IM_Descriptor[54] */
|
|
|
+ },
|
|
|
+ { /* I&M4 */
|
|
|
+ {
|
|
|
+ 0x0024, /* BlockHeader.BlockType */
|
|
|
+ 0x0038, /* BlockHeader.BlockLength */
|
|
|
+ 0x01, /* BlockHeader.BlockVersionHigh */
|
|
|
+ 0x00 /* BlockHeader.BlockVersionLow */
|
|
|
+ },
|
|
|
+ { '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' } /* IM_Signature[54] */
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/*----------------------------------------------------------------------------------------------------*/
|
|
|
+/* I&M internal functions */
|
|
|
+/*----------------------------------------------------------------------------------------------------*/
|
|
|
+
|
|
|
+void IM_incRevCounter(PNIO_UINT16* pRevCounter)
|
|
|
+{
|
|
|
+ if (*pRevCounter == 0)
|
|
|
+ {
|
|
|
+ *pRevCounter = 1;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+IM_CMP_E IM_CmpIM0(const PNIO_IM0_TYPE* pLeft, const PNIO_IM0_TYPE* pRight)
|
|
|
+{
|
|
|
+ if (
|
|
|
+ pLeft->BlockHeader.BlockLength == pRight->BlockHeader.BlockLength ||
|
|
|
+ pLeft->BlockHeader.BlockType == pRight->BlockHeader.BlockType ||
|
|
|
+ pLeft->BlockHeader.BlockVersionHigh == pRight->BlockHeader.BlockVersionHigh ||
|
|
|
+ pLeft->BlockHeader.BlockVersionLow == pRight->BlockHeader.BlockVersionLow ||
|
|
|
+ pLeft->IM_Hardware_Revision == pRight->IM_Hardware_Revision ||
|
|
|
+ pLeft->IM_Profile_ID == pRight->IM_Profile_ID ||
|
|
|
+ pLeft->IM_Profile_Specific_Type == pRight->IM_Profile_Specific_Type ||
|
|
|
+ pLeft->IM_Revision_Counter == pRight->IM_Revision_Counter ||
|
|
|
+ pLeft->IM_Supported == pRight->IM_Supported ||
|
|
|
+ pLeft->IM_Version_Major == pRight->IM_Version_Major ||
|
|
|
+ pLeft->IM_Version_Minor == pRight->IM_Version_Minor ||
|
|
|
+ STRNCMP_EQUAL == strncmp((char*)pLeft->OrderID, (char*)pRight->OrderID, LEN_IM_ORDERID) ||
|
|
|
+ pLeft->VendorIDHigh == pRight->VendorIDHigh ||
|
|
|
+ pLeft->VendorIDLow == pRight->VendorIDLow ||
|
|
|
+ STRNCMP_EQUAL == strncmp((char*)pLeft->IM_Serial_Number, (char*)pRight->IM_Serial_Number, LEN_IM_SERIAL_NUMBER) ||
|
|
|
+ STRNCMP_EQUAL == strncmp((char*)pLeft->IM_Software_Revision, (char*)pRight->IM_Software_Revision, LEN_IM_SOFTWARE_REVISION)
|
|
|
+ )
|
|
|
+ {
|
|
|
+ return IM_EQUAL;
|
|
|
+ }
|
|
|
+ return IM_READ_DIFFER;
|
|
|
+}
|
|
|
+
|
|
|
+IM_CMP_E IM_CmpIM1(const PNIO_IM1_TYPE* pLeft, const PNIO_IM1_TYPE* pRight)
|
|
|
+{
|
|
|
+ PNIO_BOOL readDiffer = PNIO_TRUE;
|
|
|
+ PNIO_BOOL writeDiffer = PNIO_TRUE;
|
|
|
+ if (pLeft->BlockHeader.BlockLength == pRight->BlockHeader.BlockLength ||
|
|
|
+ pLeft->BlockHeader.BlockType == pRight->BlockHeader.BlockType ||
|
|
|
+ pLeft->BlockHeader.BlockVersionHigh == pRight->BlockHeader.BlockVersionHigh ||
|
|
|
+ pLeft->BlockHeader.BlockVersionLow == pRight->BlockHeader.BlockVersionLow)
|
|
|
+ {
|
|
|
+ readDiffer = PNIO_FALSE;
|
|
|
+ }
|
|
|
+ if (STRNCMP_EQUAL == strncmp((char*)pLeft->IM_Tag_Function, (char*)pRight->IM_Tag_Function, LEN_IM_TAG_FUNCTION) &&
|
|
|
+ STRNCMP_EQUAL == strncmp((char*)pLeft->IM_Tag_Location, (char*)pRight->IM_Tag_Location, LEN_IM_TAG_LOCATION))
|
|
|
+ {
|
|
|
+ writeDiffer = PNIO_FALSE;
|
|
|
+ }
|
|
|
+ if ((readDiffer == PNIO_TRUE) && (writeDiffer == PNIO_TRUE))
|
|
|
+ {
|
|
|
+ return IM_READ_WRITE_DIFFER;
|
|
|
+ }
|
|
|
+ if ((readDiffer == PNIO_TRUE) && (writeDiffer == PNIO_FALSE))
|
|
|
+ {
|
|
|
+ return IM_READ_DIFFER;
|
|
|
+ }
|
|
|
+ if ((readDiffer == PNIO_FALSE) && (writeDiffer == PNIO_TRUE))
|
|
|
+ {
|
|
|
+ return IM_WRITE_DIFFER;
|
|
|
+ }
|
|
|
+ return IM_EQUAL;
|
|
|
+}
|
|
|
+
|
|
|
+IM_CMP_E IM_CmpIM2(const PNIO_IM2_TYPE* pLeft, const PNIO_IM2_TYPE* pRight)
|
|
|
+{
|
|
|
+ PNIO_BOOL readDiffer = PNIO_TRUE;
|
|
|
+ PNIO_BOOL writeDiffer = PNIO_TRUE;
|
|
|
+ if (pLeft->BlockHeader.BlockLength == pRight->BlockHeader.BlockLength ||
|
|
|
+ pLeft->BlockHeader.BlockType == pRight->BlockHeader.BlockType ||
|
|
|
+ pLeft->BlockHeader.BlockVersionHigh == pRight->BlockHeader.BlockVersionHigh ||
|
|
|
+ pLeft->BlockHeader.BlockVersionLow == pRight->BlockHeader.BlockVersionLow)
|
|
|
+ {
|
|
|
+ readDiffer = PNIO_FALSE;
|
|
|
+ }
|
|
|
+ if (STRNCMP_EQUAL == strncmp((char*)pLeft->IM_Date, (char*)pRight->IM_Date, LEN_IM_DATE))
|
|
|
+ {
|
|
|
+ writeDiffer = PNIO_FALSE;
|
|
|
+ }
|
|
|
+ if ((readDiffer == PNIO_TRUE) && (writeDiffer == PNIO_TRUE))
|
|
|
+ {
|
|
|
+ return IM_READ_WRITE_DIFFER;
|
|
|
+ }
|
|
|
+ if ((readDiffer == PNIO_TRUE) && (writeDiffer == PNIO_FALSE))
|
|
|
+ {
|
|
|
+ return IM_READ_DIFFER;
|
|
|
+ }
|
|
|
+ if ((readDiffer == PNIO_FALSE) && (writeDiffer == PNIO_TRUE))
|
|
|
+ {
|
|
|
+ return IM_WRITE_DIFFER;
|
|
|
+ }
|
|
|
+ return IM_EQUAL;
|
|
|
+}
|
|
|
+
|
|
|
+IM_CMP_E IM_CmpIM3(const PNIO_IM3_TYPE* pLeft, const PNIO_IM3_TYPE* pRight)
|
|
|
+{
|
|
|
+ PNIO_BOOL readDiffer = PNIO_TRUE;
|
|
|
+ PNIO_BOOL writeDiffer = PNIO_TRUE;
|
|
|
+ if (pLeft->BlockHeader.BlockLength == pRight->BlockHeader.BlockLength ||
|
|
|
+ pLeft->BlockHeader.BlockType == pRight->BlockHeader.BlockType ||
|
|
|
+ pLeft->BlockHeader.BlockVersionHigh == pRight->BlockHeader.BlockVersionHigh ||
|
|
|
+ pLeft->BlockHeader.BlockVersionLow == pRight->BlockHeader.BlockVersionLow)
|
|
|
+ {
|
|
|
+ readDiffer = PNIO_FALSE;
|
|
|
+ }
|
|
|
+ if (STRNCMP_EQUAL == strncmp((char*)pLeft->IM_Descriptor, (char*)pRight->IM_Descriptor, LEN_IM_DESCRIPTOR))
|
|
|
+ {
|
|
|
+ writeDiffer = PNIO_FALSE;
|
|
|
+ }
|
|
|
+ if ((readDiffer == PNIO_TRUE) && (writeDiffer == PNIO_TRUE))
|
|
|
+ {
|
|
|
+ return IM_READ_WRITE_DIFFER;
|
|
|
+ }
|
|
|
+ if ((readDiffer == PNIO_TRUE) && (writeDiffer == PNIO_FALSE))
|
|
|
+ {
|
|
|
+ return IM_READ_DIFFER;
|
|
|
+ }
|
|
|
+ if ((readDiffer == PNIO_FALSE) && (writeDiffer == PNIO_TRUE))
|
|
|
+ {
|
|
|
+ return IM_WRITE_DIFFER;
|
|
|
+ }
|
|
|
+ return IM_EQUAL;
|
|
|
+}
|
|
|
+
|
|
|
+IM_CMP_E IM_CmpIM4(const PNIO_IM4_TYPE* pLeft, const PNIO_IM4_TYPE* pRight)
|
|
|
+{
|
|
|
+ PNIO_BOOL readDiffer = PNIO_TRUE;
|
|
|
+ PNIO_BOOL writeDiffer = PNIO_TRUE;
|
|
|
+ if (pLeft->BlockHeader.BlockLength == pRight->BlockHeader.BlockLength ||
|
|
|
+ pLeft->BlockHeader.BlockType == pRight->BlockHeader.BlockType ||
|
|
|
+ pLeft->BlockHeader.BlockVersionHigh == pRight->BlockHeader.BlockVersionHigh ||
|
|
|
+ pLeft->BlockHeader.BlockVersionLow == pRight->BlockHeader.BlockVersionLow)
|
|
|
+ {
|
|
|
+ readDiffer = PNIO_FALSE;
|
|
|
+ }
|
|
|
+ if (STRNCMP_EQUAL == strncmp((char*)pLeft->IM_Signature, (char*)pRight->IM_Signature, LEN_IM_SIGNATURE))
|
|
|
+ {
|
|
|
+ writeDiffer = PNIO_FALSE;
|
|
|
+ }
|
|
|
+ if ((readDiffer == PNIO_TRUE) && (writeDiffer == PNIO_TRUE))
|
|
|
+ {
|
|
|
+ return IM_READ_WRITE_DIFFER;
|
|
|
+ }
|
|
|
+ if ((readDiffer == PNIO_TRUE) && (writeDiffer == PNIO_FALSE))
|
|
|
+ {
|
|
|
+ return IM_READ_DIFFER;
|
|
|
+ }
|
|
|
+ if ((readDiffer == PNIO_FALSE) && (writeDiffer == PNIO_TRUE))
|
|
|
+ {
|
|
|
+ return IM_WRITE_DIFFER;
|
|
|
+ }
|
|
|
+ return IM_EQUAL;
|
|
|
+}
|
|
|
+
|
|
|
+PNIO_UINT8* IM_RemTrailBlanks(const PNIO_UINT8* pBuf, int bufLen)
|
|
|
+{
|
|
|
+ static PNIO_UINT8 pNoBlanks[LINE_LENGTH_MAX];
|
|
|
+ int idx = bufLen - 1;
|
|
|
+ int copyLen = 0;
|
|
|
+ if (bufLen >= LINE_LENGTH_MAX)
|
|
|
+ {
|
|
|
+ idx = LINE_LENGTH_MAX - 2;
|
|
|
+ }
|
|
|
+ for (; idx >= 0; idx--)
|
|
|
+ {
|
|
|
+ if (pBuf[idx] != ' ')
|
|
|
+ {
|
|
|
+ copyLen = idx + 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (idx == 0) /* solely blanks found */
|
|
|
+ {
|
|
|
+ copyLen = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ strncpy((char*)pNoBlanks, (char*)pBuf, copyLen);
|
|
|
+ pNoBlanks[copyLen] = '\0';
|
|
|
+ return pNoBlanks;
|
|
|
+}
|
|
|
+
|
|
|
+/* pSrc has to be null-terminated */
|
|
|
+PNIO_BOOL IM_CopyQuotedString(PNIO_UINT8* pDst, PNIO_UINT8* pSrc, size_t maxSize)
|
|
|
+{
|
|
|
+ PNIO_UINT8* pTmp;
|
|
|
+ size_t copyLen;
|
|
|
+ pSrc = (PNIO_UINT8*) strchr((char*)pSrc, '"');
|
|
|
+ if (!pSrc)
|
|
|
+ {
|
|
|
+ return PNIO_FALSE;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ pSrc++;
|
|
|
+ }
|
|
|
+ pTmp = (PNIO_UINT8*)strrchr((char*)pSrc, '"');
|
|
|
+ if (!pTmp)
|
|
|
+ {
|
|
|
+ return PNIO_FALSE;
|
|
|
+ }
|
|
|
+ copyLen = pTmp - pSrc;
|
|
|
+ if (copyLen > maxSize)
|
|
|
+ {
|
|
|
+ copyLen = maxSize;
|
|
|
+ }
|
|
|
+ strncpy((char*)pDst, (char*)pSrc, copyLen);
|
|
|
+ return PNIO_TRUE;
|
|
|
+}
|
|
|
+
|
|
|
+void IM_CopySwapIm1FromBuf(
|
|
|
+ PNIO_IM1_TYPE* pIm, /* [out] */
|
|
|
+ PNIO_UINT8* const pBuf) /* [in] */
|
|
|
+{
|
|
|
+ *pIm = *(PNIO_IM1_TYPE*)pBuf;
|
|
|
+ pIm->BlockHeader.BlockType = SWAP_16(((PNIO_IM1_TYPE*)pBuf)->BlockHeader.BlockType);
|
|
|
+ pIm->BlockHeader.BlockLength = SWAP_16(((PNIO_IM1_TYPE*)pBuf)->BlockHeader.BlockLength);
|
|
|
+}
|
|
|
+
|
|
|
+void IM_CopySwapIm2FromBuf(
|
|
|
+ PNIO_IM2_TYPE* pIm, /* [out] */
|
|
|
+ PNIO_UINT8* const pBuf) /* [in] */
|
|
|
+{
|
|
|
+ *pIm = *(PNIO_IM2_TYPE*)pBuf;
|
|
|
+ pIm->BlockHeader.BlockType = SWAP_16(((PNIO_IM2_TYPE*)pBuf)->BlockHeader.BlockType);
|
|
|
+ pIm->BlockHeader.BlockLength = SWAP_16(((PNIO_IM2_TYPE*)pBuf)->BlockHeader.BlockLength);
|
|
|
+}
|
|
|
+
|
|
|
+void IM_CopySwapIm3FromBuf(
|
|
|
+ PNIO_IM3_TYPE* pIm, /* [out] */
|
|
|
+ PNIO_UINT8* const pBuf) /* [in] */
|
|
|
+{
|
|
|
+ *pIm = *(PNIO_IM3_TYPE*)pBuf;
|
|
|
+ pIm->BlockHeader.BlockType = SWAP_16(((PNIO_IM3_TYPE*)pBuf)->BlockHeader.BlockType);
|
|
|
+ pIm->BlockHeader.BlockLength = SWAP_16(((PNIO_IM3_TYPE*)pBuf)->BlockHeader.BlockLength);
|
|
|
+}
|
|
|
+
|
|
|
+void IM_CopySwapIm4FromBuf(
|
|
|
+ PNIO_IM4_TYPE* pIm, /* [out] */
|
|
|
+ PNIO_UINT8* const pBuf) /* [in] */
|
|
|
+{
|
|
|
+ *pIm = *(PNIO_IM4_TYPE*)pBuf;
|
|
|
+ pIm->BlockHeader.BlockType = SWAP_16(((PNIO_IM4_TYPE*)pBuf)->BlockHeader.BlockType);
|
|
|
+ pIm->BlockHeader.BlockLength = SWAP_16(((PNIO_IM4_TYPE*)pBuf)->BlockHeader.BlockLength);
|
|
|
+}
|
|
|
+
|
|
|
+PNIO_BOOL IM_CopySwapBufFromIm(
|
|
|
+ PNIO_UINT8* pBuf, /* [out] */
|
|
|
+ IM_DATA const* pIm, /* [in] */
|
|
|
+ IM0_idx_e idx) /* [in] */
|
|
|
+{
|
|
|
+ switch (idx)
|
|
|
+ {
|
|
|
+ case IM0:
|
|
|
+ *((PNIO_IM0_TYPE*)pBuf) = pIm->im0;
|
|
|
+ ((PNIO_IM0_TYPE*)pBuf)->BlockHeader.BlockType = SWAP_16(pIm->im0.BlockHeader.BlockType);
|
|
|
+ ((PNIO_IM0_TYPE*)pBuf)->BlockHeader.BlockLength = SWAP_16(pIm->im0.BlockHeader.BlockLength);
|
|
|
+ ((PNIO_IM0_TYPE*)pBuf)->IM_Hardware_Revision = SWAP_16(pIm->im0.IM_Hardware_Revision);
|
|
|
+ /* ((PNIO_IM0_TYPE *)pBuf)->IM_Software_Revision = SWAP_32(pIm->im0.IM_Software_Revision);*/
|
|
|
+ ((PNIO_IM0_TYPE*)pBuf)->IM_Revision_Counter = SWAP_16(pIm->im0.IM_Revision_Counter);
|
|
|
+ ((PNIO_IM0_TYPE*)pBuf)->IM_Profile_Specific_Type = SWAP_16(pIm->im0.IM_Profile_Specific_Type);
|
|
|
+ ((PNIO_IM0_TYPE*)pBuf)->IM_Profile_ID = SWAP_16(pIm->im0.IM_Profile_ID);
|
|
|
+ ((PNIO_IM0_TYPE*)pBuf)->IM_Supported = SWAP_16(pIm->im0.IM_Supported);
|
|
|
+ break;
|
|
|
+ case IM1:
|
|
|
+ *((PNIO_IM1_TYPE*)pBuf) = pIm->im1;
|
|
|
+ ((PNIO_IM1_TYPE*)pBuf)->BlockHeader.BlockType = SWAP_16(pIm->im1.BlockHeader.BlockType);
|
|
|
+ ((PNIO_IM1_TYPE*)pBuf)->BlockHeader.BlockLength = SWAP_16(pIm->im1.BlockHeader.BlockLength);
|
|
|
+ break;
|
|
|
+ case IM2:
|
|
|
+ *((PNIO_IM2_TYPE*)pBuf) = pIm->im2;
|
|
|
+ ((PNIO_IM2_TYPE*)pBuf)->BlockHeader.BlockType = SWAP_16(pIm->im2.BlockHeader.BlockType);
|
|
|
+ ((PNIO_IM2_TYPE*)pBuf)->BlockHeader.BlockLength = SWAP_16(pIm->im2.BlockHeader.BlockLength);
|
|
|
+ break;
|
|
|
+ case IM3:
|
|
|
+ *((PNIO_IM3_TYPE*)pBuf) = pIm->im3;
|
|
|
+ ((PNIO_IM3_TYPE*)pBuf)->BlockHeader.BlockType = SWAP_16(pIm->im3.BlockHeader.BlockType);
|
|
|
+ ((PNIO_IM3_TYPE*)pBuf)->BlockHeader.BlockLength = SWAP_16(pIm->im3.BlockHeader.BlockLength);
|
|
|
+ break;
|
|
|
+ case IM4:
|
|
|
+ *((PNIO_IM4_TYPE*)pBuf) = pIm->im4;
|
|
|
+ ((PNIO_IM4_TYPE*)pBuf)->BlockHeader.BlockType = SWAP_16(pIm->im4.BlockHeader.BlockType);
|
|
|
+ ((PNIO_IM4_TYPE*)pBuf)->BlockHeader.BlockLength = SWAP_16(pIm->im4.BlockHeader.BlockLength);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return PNIO_TRUE;
|
|
|
+}
|
|
|
+/* Diese Funktion gibt die Groesse des Datensatzes zurueck */
|
|
|
+PNIO_UINT32 IM_SizeofImDatarec(PNIO_UINT32 RecordIndex)
|
|
|
+{
|
|
|
+ switch (RecordIndex)
|
|
|
+ {
|
|
|
+ case IM0:
|
|
|
+ return (sizeof(PNIO_IM0_TYPE));
|
|
|
+ case IM1:
|
|
|
+ return (sizeof(PNIO_IM1_TYPE));
|
|
|
+ case IM2:
|
|
|
+ return (sizeof(PNIO_IM2_TYPE));
|
|
|
+ case IM3:
|
|
|
+ return (sizeof(PNIO_IM3_TYPE));
|
|
|
+ case IM4:
|
|
|
+ return (sizeof(PNIO_IM4_TYPE));
|
|
|
+ default:
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* check if the given RacordIndex is supported */
|
|
|
+PNIO_BOOL IM_IndexSupported(PNIO_UINT32 RecordIndex, PNIO_UINT16 IM_Supported)
|
|
|
+{
|
|
|
+ /* && (IM_Supported&0x01) */
|
|
|
+ if (((RecordIndex == IM0)) ||
|
|
|
+ ((RecordIndex == IM1) && (IM_Supported & 0x02)) ||
|
|
|
+ ((RecordIndex == IM2) && (IM_Supported & 0x04)) ||
|
|
|
+ ((RecordIndex == IM3) && (IM_Supported & 0x08)) ||
|
|
|
+ ((RecordIndex == IM4) && (IM_Supported & 0x10)))
|
|
|
+ {
|
|
|
+ return PNIO_TRUE;
|
|
|
+ }
|
|
|
+ return PNIO_FALSE;
|
|
|
+}
|
|
|
+
|
|
|
+/* set error code */
|
|
|
+void setPnioRwError(PNIO_ERR_STAT* pPnioState, PNIO_UINT8 ErrCode1)
|
|
|
+{
|
|
|
+ /**** if an error occured, you must specify it according IEC 61158-6 */
|
|
|
+ pPnioState->ErrCode = 0xdf; /* IODWriteRes with ErrorDecode = PNIORW */
|
|
|
+ pPnioState->ErrDecode = 0x80; /* PNIORW */
|
|
|
+ pPnioState->ErrCode1 = ErrCode1;
|
|
|
+ pPnioState->ErrCode2 = 0; /* here dont care */
|
|
|
+ pPnioState->AddValue1 = 0; /* here dont care */
|
|
|
+ pPnioState->AddValue2 = 0; /* here dont care */
|
|
|
+}
|
|
|
+
|
|
|
+/*----------------------------------------------------------------------------------------------------*/
|
|
|
+/* I&M external functions */
|
|
|
+/*----------------------------------------------------------------------------------------------------*/
|
|
|
+
|
|
|
+/* Read I&M data from pBuf */
|
|
|
+void IM_recWrite(PNIO_UINT32 RecordIndex, PNIO_DEV_ADDR Addr, PNIO_UINT32* pBufLen, PNIO_UINT8* pBuf, PNIO_ERR_STAT* pPnioState)
|
|
|
+{
|
|
|
+ IM_CMP_E imCmp = IM_EQUAL;
|
|
|
+ IM_DATA* pIm = NULL;
|
|
|
+ int id = 0;
|
|
|
+
|
|
|
+ *pBufLen = 0;
|
|
|
+ id = addrToId(Addr);
|
|
|
+ if (id < 0)
|
|
|
+ {
|
|
|
+ setPnioRwError(pPnioState, 0xb2); /* access: invalid slot/subslot */
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ pIm = &im_work[id];
|
|
|
+ if (!IM_IndexSupported(RecordIndex, im_work[id].im0.IM_Supported))
|
|
|
+ {
|
|
|
+ setPnioRwError(pPnioState, 0xa9); /* application: feature not supported */
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ switch (RecordIndex)
|
|
|
+ {
|
|
|
+ case IM0:
|
|
|
+ setPnioRwError(pPnioState, 0xb6); /* access: access denied */
|
|
|
+ return;
|
|
|
+ case IM1:
|
|
|
+ {
|
|
|
+ PNIO_IM1_TYPE im;
|
|
|
+ if (pBuf == 0)
|
|
|
+ {
|
|
|
+ im = im_default.im1;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ IM_CopySwapIm1FromBuf(&im, pBuf);
|
|
|
+ }
|
|
|
+ imCmp = IM_CmpIM1(&im, &pIm->im1);
|
|
|
+ if ((imCmp == IM_READ_DIFFER) || (imCmp == IM_READ_WRITE_DIFFER))
|
|
|
+ {
|
|
|
+ setPnioRwError(pPnioState, 0xb4); /* Access: invalid area */
|
|
|
+ }
|
|
|
+ else
|
|
|
+ if (imCmp == IM_WRITE_DIFFER)
|
|
|
+ {
|
|
|
+ pIm->im1 = im;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case IM2:
|
|
|
+ {
|
|
|
+ PNIO_IM2_TYPE im;
|
|
|
+ if (pBuf == 0)
|
|
|
+ {
|
|
|
+ im = im_default.im2;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ IM_CopySwapIm2FromBuf(&im, pBuf);
|
|
|
+ }
|
|
|
+ imCmp = IM_CmpIM2(&im, &pIm->im2);
|
|
|
+ if ((imCmp == IM_READ_DIFFER) || (imCmp == IM_READ_WRITE_DIFFER))
|
|
|
+ {
|
|
|
+ setPnioRwError(pPnioState, 0xb4); /* Access: invalid area */
|
|
|
+ }
|
|
|
+ else
|
|
|
+ if (imCmp == IM_WRITE_DIFFER)
|
|
|
+ {
|
|
|
+ pIm->im2 = im;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case IM3:
|
|
|
+ {
|
|
|
+ PNIO_IM3_TYPE im;
|
|
|
+ if (pBuf == 0)
|
|
|
+ {
|
|
|
+ im = im_default.im3;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ IM_CopySwapIm3FromBuf(&im, pBuf);
|
|
|
+ }
|
|
|
+ imCmp = IM_CmpIM3(&im, &pIm->im3);
|
|
|
+ if ((imCmp == IM_READ_DIFFER) || (imCmp == IM_READ_WRITE_DIFFER))
|
|
|
+ {
|
|
|
+ setPnioRwError(pPnioState, 0xb4); /* Access: invalid area */
|
|
|
+ }
|
|
|
+ else
|
|
|
+ if (imCmp == IM_WRITE_DIFFER)
|
|
|
+ {
|
|
|
+ pIm->im3 = im;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case IM4:
|
|
|
+ setPnioRwError(pPnioState, 0xb6); /* access: access denied */
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ *pBufLen = IM_SizeofImDatarec(RecordIndex);
|
|
|
+
|
|
|
+ /* store data in any case (e.g. switched off) */
|
|
|
+ if( imCmp == IM_WRITE_DIFFER)
|
|
|
+ {
|
|
|
+ /* do not increment. always 0 */
|
|
|
+ /* IM_incRevCounter(&pIm->im0.IM_Revision_Counter); */
|
|
|
+ IM_DataToStore("im.conf");
|
|
|
+ }
|
|
|
+
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+/* Write I&M data into pBuf */
|
|
|
+void IM_RecRead(PNIO_UINT32 RecordIndex, PNIO_DEV_ADDR Addr, PNIO_UINT32* pBufLen, PNIO_UINT8* pBuf, PNIO_ERR_STAT* pPnioState)
|
|
|
+{
|
|
|
+ int id = addrToId(Addr);
|
|
|
+ if (id < 0)
|
|
|
+ {
|
|
|
+ setPnioRwError(pPnioState, 0xb2); /* access: invalid slot/subslot */
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!IM_IndexSupported(RecordIndex, im_work[id].im0.IM_Supported))
|
|
|
+ {
|
|
|
+ setPnioRwError(pPnioState, 0xa9); /* application: feature not supported */
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ *pBufLen = IM_SizeofImDatarec(RecordIndex);
|
|
|
+ IM_CopySwapBufFromIm(pBuf, &im_work[id], (IM0_idx_e)RecordIndex);
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+int copy_string(char* dstBuf, const char* srcBuf, size_t len)
|
|
|
+{
|
|
|
+ int n;
|
|
|
+ for (n=0; n<len; n++)
|
|
|
+ {
|
|
|
+ if ((dstBuf[n] < 0x20) || (srcBuf[n] > 0x7E))
|
|
|
+ {
|
|
|
+ /* Control character */
|
|
|
+ dstBuf[n] = ' ';
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ /* Visible character */
|
|
|
+ dstBuf[n] = srcBuf[n];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+void set_serial_string( char* serial_str)
|
|
|
+{
|
|
|
+ int n = 0;
|
|
|
+ size_t serial_length = 0;
|
|
|
+
|
|
|
+ if( !g_annot_serial)
|
|
|
+ {
|
|
|
+ g_annot_serial = (PNIO_UINT8*)malloc(MAX_SERIAL_LENGTH+1);
|
|
|
+ }
|
|
|
+
|
|
|
+ memset( g_annot_serial, ' ' , MAX_SERIAL_LENGTH+1);
|
|
|
+ g_annot_serial[MAX_SERIAL_LENGTH+1] = 0;
|
|
|
+
|
|
|
+ serial_length = strlen(serial_str);
|
|
|
+ if( serial_length > MAX_SERIAL_LENGTH-1) serial_length = MAX_SERIAL_LENGTH-1;
|
|
|
+ copy_string((char*)g_annot_serial,serial_str,serial_length);
|
|
|
+}
|
|
|
+
|
|
|
+void IM_initImRecords(void)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ SERV_CP_FW_INFO_TYPE servInfo;
|
|
|
+ SERV_CP_ANNOTATION_TYPE annoInfo;
|
|
|
+
|
|
|
+ /* get actual serial number only on first call to this function, since the serial number can't change during runtime */
|
|
|
+ if (g_annot_serial == 0)
|
|
|
+ {
|
|
|
+ g_annot_serial = (PNIO_UINT8*)malloc(sizeof(annoInfo.serial_number));
|
|
|
+ memset(g_annot_serial,0,sizeof(annoInfo.serial_number));
|
|
|
+ if( SERV_CP_get_annotation_data(1, &annoInfo) == PNIO_OK &&
|
|
|
+ SERV_CP_get_fw_info(1,&servInfo) == PNIO_OK)
|
|
|
+ {
|
|
|
+ set_serial_string( annoInfo.mode == PNIO_CP_ANNO_COMPLETE ?
|
|
|
+ (char*)&annoInfo.serial_number[0] :
|
|
|
+ (char*)&servInfo.cp_ser_nr[0]);
|
|
|
+#if 0
|
|
|
+ size_t length = 0;
|
|
|
+
|
|
|
+ if( annoInfo.mode != PNIO_CP_ANNO_NOT_USED)
|
|
|
+ {
|
|
|
+ length = strlen(annoInfo.serial_number);
|
|
|
+ if( length > sizeof(servInfo.cp_ser_nr)) /* maximum of 16 */
|
|
|
+ {
|
|
|
+ length = sizeof(servInfo.cp_ser_nr);
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy(&g_annot_serial[0], &annoInfo.serial_number[0], length);
|
|
|
+ }
|
|
|
+ else if ((SERV_CP_get_fw_info(1, &servInfo) == PNIO_OK))
|
|
|
+ {
|
|
|
+ length = strlen(servInfo.cp_ser_nr);
|
|
|
+ if( length > sizeof(servInfo.cp_ser_nr)) /* maximum of 16 */
|
|
|
+ {
|
|
|
+ length = sizeof(servInfo.cp_ser_nr);
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy(&g_annot_serial[0], &servInfo.cp_ser_nr[0], length);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ /* failed */
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ /* failed to get fw info */
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ free(im_work);
|
|
|
+ im_work = (IM_DATA*)malloc(sizeof(IM_DATA) * g_device_data.nrOfSubmodules);
|
|
|
+ for (i = 0; i < g_device_data.nrOfSubmodules; i++)
|
|
|
+ {
|
|
|
+ im_work[i] = im_default;
|
|
|
+
|
|
|
+ im_work[i].im0.VendorIDHigh = (g_device_data.VendorId >> 8) & 0xff;
|
|
|
+ im_work[i].im0.VendorIDLow = g_device_data.VendorId & 0xff;
|
|
|
+ memcpy(&im_work[i].im0.OrderID, g_annot_selected.OrderId, MAX_ORDER_ID_LENGTH);
|
|
|
+ im_work[i].im0.IM_Hardware_Revision = g_annot_selected.HwRevision;
|
|
|
+ im_work[i].im0.IM_Software_Revision[0] = (PNIO_UINT8)g_annot_selected.SwRevisionPrefix;
|
|
|
+ im_work[i].im0.IM_Software_Revision[1] = (PNIO_UINT8)g_annot_selected.SwRevision1;
|
|
|
+ im_work[i].im0.IM_Software_Revision[2] = (PNIO_UINT8)g_annot_selected.SwRevision2;
|
|
|
+ im_work[i].im0.IM_Software_Revision[3] = (PNIO_UINT8)g_annot_selected.SwRevision3;
|
|
|
+ memcpy(&im_work[i].im0.IM_Serial_Number, g_annot_serial, sizeof(im_work[i].im0.IM_Serial_Number));
|
|
|
+
|
|
|
+ if ((g_device_data.pDeviceData[i].Addr.u.Geo.Slot == 1) &&
|
|
|
+ ((g_device_data.pDeviceData[i].Addr.u.Geo.Subslot == 0x8000)
|
|
|
+ || (g_device_data.pDeviceData[i].Addr.u.Geo.Subslot == 0x8001)
|
|
|
+ || (g_device_data.pDeviceData[i].Addr.u.Geo.Subslot == 0x8002)
|
|
|
+ || (g_device_data.pDeviceData[i].Addr.u.Geo.Subslot == 0x8003)
|
|
|
+ || (g_device_data.pDeviceData[i].Addr.u.Geo.Subslot == 0x8004)))
|
|
|
+ {
|
|
|
+ im_work[i].im0.IM_Profile_Specific_Type = 0x04; /* communication module -> www.profibus.com/IM/Device_ID_Table_6102.xml */
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void IM_DataFromStore(const char* pName)
|
|
|
+{
|
|
|
+ FILE* pFile;
|
|
|
+ PNIO_UINT8 line[LINE_LENGTH_MAX];
|
|
|
+ IM_PERSISTENT_DATA_e idx;
|
|
|
+ int sModIdx;
|
|
|
+ pFile = fopen(pName, "r");
|
|
|
+ if (pFile == NULL)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (sModIdx = 0; sModIdx < g_device_data.nrOfSubmodules; sModIdx++)
|
|
|
+ {
|
|
|
+ IM_DATA* pIm = &im_work[sModIdx];
|
|
|
+ /* override default IM values by stored values */
|
|
|
+ while (fgets((char*)line, LINE_LENGTH_MAX, pFile) != NULL)
|
|
|
+ {
|
|
|
+ char* pPos = NULL;
|
|
|
+ int sectionIdx;
|
|
|
+ /* ignore comments -> read next line */
|
|
|
+ if ((line[0] == ';') || (line[0] == '#'))
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ /* continue until submodule section is found */
|
|
|
+ sscanf((char*)line, "[SUBMOD%i]", §ionIdx);
|
|
|
+ if (sectionIdx != sModIdx)
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ /* find IM item in current line */
|
|
|
+ for (idx = (IM_PERSISTENT_DATA_e)0; idx < NUMOF_PERSISTENT_IM_ITEMS; idx = (IM_PERSISTENT_DATA_e)((int)idx + 1))
|
|
|
+ {
|
|
|
+ size_t size = strlen(name_IM_PERSISTENT_DATA[idx]);
|
|
|
+ if (STRNCMP_EQUAL == strncmp((char*)line, name_IM_PERSISTENT_DATA[idx], size))
|
|
|
+ {
|
|
|
+ pPos = (char*)line + size;
|
|
|
+ /* ignore blanks etc */
|
|
|
+ while ((*pPos == ' ') || (*pPos == '='))
|
|
|
+ {
|
|
|
+ pPos++;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (pPos == NULL) /* no IM item found */
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ /* read IM value */
|
|
|
+ switch (idx)
|
|
|
+ {
|
|
|
+ case IM_Revision_Counter:
|
|
|
+ {
|
|
|
+ int val;
|
|
|
+ sscanf(pPos, "%i", &val);
|
|
|
+ if ((val > 0) && (val <= 0xffff))
|
|
|
+ {
|
|
|
+ pIm->im0.IM_Revision_Counter = (PNIO_UINT16) val;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case IM_Tag_Function:
|
|
|
+ IM_CopyQuotedString(pIm->im1.IM_Tag_Function, line, sizeof(pIm->im1.IM_Tag_Function));
|
|
|
+ break;
|
|
|
+ case IM_Tag_Location:
|
|
|
+ IM_CopyQuotedString(pIm->im1.IM_Tag_Location, line, sizeof(pIm->im1.IM_Tag_Location));
|
|
|
+ break;
|
|
|
+ case IM_Date:
|
|
|
+ IM_CopyQuotedString(pIm->im2.IM_Date, line, sizeof(pIm->im2.IM_Date));
|
|
|
+ break;
|
|
|
+ case IM_Descriptor:
|
|
|
+ IM_CopyQuotedString(pIm->im3.IM_Descriptor, line, sizeof(pIm->im3.IM_Descriptor));
|
|
|
+ break;
|
|
|
+ case IM_Signature:
|
|
|
+ IM_CopyQuotedString(pIm->im4.IM_Signature, line, sizeof(pIm->im4.IM_Signature));
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ fclose(pFile);
|
|
|
+}
|
|
|
+
|
|
|
+void IM_DataToStore(const char* pName)
|
|
|
+{
|
|
|
+ FILE* pFile;
|
|
|
+ int sModIdx;
|
|
|
+ pFile = fopen(pName, "w");
|
|
|
+ if (pFile == NULL)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ for (sModIdx = 0; sModIdx < g_device_data.nrOfSubmodules; sModIdx++)
|
|
|
+ {
|
|
|
+ const IM_DATA* pIm = &im_work[sModIdx];
|
|
|
+ if (sModIdx)
|
|
|
+ {
|
|
|
+ fprintf(pFile, "\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ fprintf(pFile, "[SUBMOD%i]\n", sModIdx);
|
|
|
+ fprintf(pFile, "%s = 0x%04x\n", name_IM_PERSISTENT_DATA[IM_Revision_Counter],
|
|
|
+ pIm->im0.IM_Revision_Counter);
|
|
|
+ if (pIm->im0.IM_Supported & 0x02)
|
|
|
+ {
|
|
|
+ fprintf(pFile, "%s = \"%s\"\n", name_IM_PERSISTENT_DATA[IM_Tag_Function],
|
|
|
+ IM_RemTrailBlanks(pIm->im1.IM_Tag_Function, sizeof(pIm->im1.IM_Tag_Function)));
|
|
|
+ fprintf(pFile, "%s = \"%s\"\n", name_IM_PERSISTENT_DATA[IM_Tag_Location],
|
|
|
+ IM_RemTrailBlanks(pIm->im1.IM_Tag_Location, sizeof(pIm->im1.IM_Tag_Location)));
|
|
|
+ }
|
|
|
+ if (pIm->im0.IM_Supported & 0x04)
|
|
|
+ {
|
|
|
+ fprintf(pFile, "%s = \"%s\"\n", name_IM_PERSISTENT_DATA[IM_Date],
|
|
|
+ IM_RemTrailBlanks(pIm->im2.IM_Date, sizeof(pIm->im2.IM_Date)));
|
|
|
+ }
|
|
|
+ if (pIm->im0.IM_Supported & 0x08)
|
|
|
+ {
|
|
|
+ fprintf(pFile, "%s = \"%s\"\n", name_IM_PERSISTENT_DATA[IM_Descriptor],
|
|
|
+ IM_RemTrailBlanks(pIm->im3.IM_Descriptor, sizeof(pIm->im3.IM_Descriptor)));
|
|
|
+ }
|
|
|
+ if (pIm->im0.IM_Supported & 0x10)
|
|
|
+ {
|
|
|
+ fprintf(pFile, "%s = \"%s\"\n", name_IM_PERSISTENT_DATA[IM_Signature],
|
|
|
+ IM_RemTrailBlanks(pIm->im4.IM_Signature, sizeof(pIm->im4.IM_Signature)));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ fclose(pFile);
|
|
|
+}
|