📄 ci_util.c
字号:
/****************************************************************************
*****************************************************************************
**
** 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 + -