⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ci_util.c

📁 基于EthernetIP协议的应用程序,可以读取AB公司Controllogix系列Ethernetip协议PLC数据. 此软件代码可用于工业控制.
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*****************************************************************************
**
** File Name
** ---------
**
** CI_UTIL.C
**
*****************************************************************************
*****************************************************************************
**
** Description
** -----------
**
** ControlNet International General Utilities.
**
** This source module contains a collection of ControlNet related utilities
** that are primarily involved with message parsing.
**
*****************************************************************************
*****************************************************************************
**
** Source Change Indices
** ---------------------
**
** Porting: <none>0----<major>         Customization: <none>0----<major>
**
*****************************************************************************
*****************************************************************************
**                                                                         **
** ETHERNET/IP EXAMPLE CODE                                                **
** COPYRIGHT (c) 2000-2005 ODVA (Open DeviceNet Vendor Association)		   **
**						   & ControlNet International Ltd.                 **
**                                                                         **
** All rights reserved, except as specifically licensed in writing.        **
** Use of the Ethernet/IP Example Protocol Software is subject to          **
** ODVA's and ControlNet International's Terms of Use Agreement.           **
** The following work constitutes example program code and is intended     **
** merely to illustrate useful programming techniques.  The user is        **
** responsible for applying the code correctly.  The code is provided      **
** AS IS without warranty and is in no way guaranteed to be error-free.    **
**                                                                         **
*****************************************************************************
*****************************************************************************
*/

/****************************************************************************
*****************************************************************************
**
** Change Log
** ----------
**
**
*****************************************************************************
*****************************************************************************
*/

/*
** See if this object is to be included.
*/

#include "ab.h"
#ifdef CD_EN_OBJECTS

#include "gs.h"         /* general services public interfaces              */
#include "cb.h"         /* communication buffers public interfaces         */
#include "ci.h"         /* General ControlNet definitions                  */
#include "cm.h"         /* Connection Manager public interfaces            */



/****************************************************************************
**
** Public Services
**
*****************************************************************************
*/

/*---------------------------------------------------------------------------
** CI_IoiPathSize()
**---------------------------------------------------------------------------
*/

UINT16 CI_IoiPathSize( CB_ComBufType *pComBuf, UINT16 iOffset )
{
   UINT8 *pb;


   /*
   ** Get the base packet address.
   ** Handle the 3 different IOI/Path cases.
   */

   pb = CB_GetDataPtrComBuf( pComBuf );

   if( iOffset == 0 )
   {
      /*
      ** IOI.  Include the size of the base IOI structure.
      */

      return( sizeof( CI_IoiType ) + ( ( (CI_IoiType*)(pb) )->bIoiSize * 2 ) );
   }

   /*
   ** Path. Add the offset to the base packet pointer.
   ** This points to the size of the path.
   **
   ** If the offset is odd, this is a path at the end of a forward open/close.
   ** Include the path plus 1 byte for the size.
   ** If the offset is even, this is a generic path.
   ** Include the path plus 1 byte for the size plus 1 byte of pad.
   */

   pb += iOffset;
   return( *pb * 2 + ( ( iOffset & 1 ) ? 1 : 2 ) );

} /* end of CI_IoiPathSize() */



/*---------------------------------------------------------------------------
** CI_ParseIoiClassInstance()
**---------------------------------------------------------------------------
*/

UINT8 CI_ParseIoiClassInstance( CB_ComBufType *pComBuf, UINT16 *piClass, UINT16 *piInstance )
{
   UINT8  bGRC;
   UINT8  bSegType;
   UINT8   *pbService;
   UINT8   *pbSize;


   /*
   ** Parse off and verify the class first.
   */

   bGRC = CI_ParseIoiSegment( pComBuf, &bSegType, piClass, TRUE );

   if( bGRC != SUCCESS )
   {
      return( bGRC );
   }

   if( bSegType != CI_LOGICAL_SEG_CLASS )
   {
      return( CI_GRC_BAD_PATH );
   }

   /*
   ** Test the Unconnected Send's Ioi Size to detect a missing
   ** instance segment for legacy ControlNet products.
   */

   pbService = (UINT8*)(CB_GetDataPtrComBuf( pComBuf ));
   pbSize = pbService + 1;

   if( ( *pbService == CM_SC_UNCONNECTED_SEND ) && ( *pbSize == 0 ) )
   {
      /*
      ** This is a patch enabling unconnected messages missing the instance segment
      ** in the ioi to be accepted and sets the instance equal to one.
      ** This deals with a ktcx deficiency which does not include the instance
      ** segment in unconnected sends, 0x52 service.
      */

      bSegType = CI_LOGICAL_SEG_INSTANCE;
      *piInstance = 1;
   }
   else
   {
      /*
      ** Now parse off and verify the instance.
      */

      bGRC = CI_ParseIoiSegment( pComBuf, &bSegType, piInstance, TRUE );

      if( bGRC != SUCCESS )
      {
         return( bGRC );
      }

      if( bSegType != CI_LOGICAL_SEG_INSTANCE )
      {
         return( CI_GRC_BAD_PATH );
      }

	pbService = (UINT8*)(CB_GetDataPtrComBuf( pComBuf ));
	pbSize = pbService + 1;
	if( *pbService==CM_SC_FWD_CLOSE ){
		if( *pbSize )
		{
			return( CI_GRC_BAD_PATH );
		}
	}

   }

   /*
   ** Properly formatted class and instance segments parsed.
   */

   return( CI_GRC_SUCCESS );

} /* end of CI_ParseIoiClassInstance() */



/*---------------------------------------------------------------------------
** CI_PrependIoi()
**---------------------------------------------------------------------------
*/

void CI_PrependIoi( CB_ComBufType *pCombuf,
                    UINT8          bRequestCode,
                    UINT8          bClass,
                    UINT16         iInstance,
                    UINT16         iExtraIOI )
{
   CI_IoiCIType *pHeader;


   /*
   ** If the instance is bigger than a byte, stick it on first.
   */

   if( iInstance > 255 )
   {
      CB_PrependComBuf( pCombuf, &iInstance, sizeof( UINT16 ) );
      iExtraIOI++;
   }

   /*
   ** Make room for the basic class/instance IOI.
   */

   CB_ExpandComBuf( pCombuf, sizeof( CI_IoiCIType ) );

   /*
   ** Fill in the details,
   */

   pHeader = CB_GetDataPtrComBuf( pCombuf );
   pHeader->bService     = bRequestCode;
   pHeader->bIoiSize     = 2 + iExtraIOI;
   pHeader->bClassSeg    = CI_LOGICAL_SEGMENT | CI_LOGICAL_SEG_CLASS;
   pHeader->bClass       = bClass;
   pHeader->bInstanceSeg = CI_LOGICAL_SEGMENT | CI_LOGICAL_SEG_INSTANCE;

   /*
   ** Special handling for instances based on size.
   */

   if( iInstance <= 255 )
   {
      pHeader->bInstance = iInstance;
   }
   else
   {
      pHeader->bInstanceSeg |= CI_LOGICAL_SEG_16_BIT;
      pHeader->bInstance = 0;
   }

} /* end of CI_PrependIoi() */



/*---------------------------------------------------------------------------
** CI_PrependReplyHeader()
**---------------------------------------------------------------------------
*/

void CI_PrependReplyHeader( CB_ComBufType *pCombuf,
                            UINT8          bRequestCode,
                            UINT8          bGenStatus,
                            UINT16         iObjStatus )
{
   CI_LeBadReplyHeaderType *pHeader;


   /*
   ** Make room for the appropriate header.
   */

   CB_ExpandComBuf( pCombuf,
                    iObjStatus == 0 ?
                    sizeof( CI_GoodReplyHeaderType ) :
                    sizeof( CI_LeBadReplyHeaderType ) );

   pHeader = CB_GetDataPtrComBuf( pCombuf );

   /*
   ** Fill in the common details,
   ** then include the object status or not per its value.
   */

   pHeader->bService        = bRequestCode | CI_SC_REPLY_MASK;
   pHeader->bIoiSize        = 0;
   pHeader->bGenStatus      = bGenStatus;

   if( iObjStatus == 0 )
   {
      pHeader->bObjStatusSize = 0;
   }
   else
   {
      pHeader->bObjStatusSize = 1;
      pHeader->iLeObjStatus = UC_iTOiLe( iObjStatus );
   }

} /* end of CI_PrependReplyHeader() */



/*---------------------------------------------------------------------------
** CI_PrependReplyHeaderWithExtendedERC()
**---------------------------------------------------------------------------
*/

void CI_PrependReplyHeaderWithExtendedERC
       ( CB_ComBufType *pCombuf,
         UINT8          bRequestCode,
         UINT8          bGenStatus,
         UINT16         iERClength,
         UINT16        *piERC
       )
{
   CI_LeBadReplyHeaderType *pHeader;
   LeUINT16 *piLeObjStatus;
   

   /*
   ** Make room for the appropriate header.
   */

   CB_ExpandComBuf( pCombuf,
                    iERClength == 0 ?
                    sizeof( CI_GoodReplyHeaderType ) :
                    ( sizeof( CI_LeBadReplyHeaderType ) + ( iERClength - 1 ) ) );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -