📄 ecinterface.c
字号:
SUB_MALLOC( aInstance->itsAttributes, t_Attribute *, theAttributesCount*sizeof( t_Attribute ) );
aInstance->itsAttributesCount = theAttributesCount;
/* ! */
RET(ECI_E_SUCCESS,0);
}
int EC_CreateClassAttribute( unsigned int theClassCode, unsigned char theAttributeCode, unsigned int theIsReadOnly, void *theDataPtr, int theDataSize ){
/*
** create a new Attribute in the Class identified by theClassCode
*/
t_Class *aClass;
t_Attribute *aAttribute;
/* ! find Class identified by theClassCode */
if( (aClass=FindClass( theClassCode ))==NULL )
RET(gECIError,-1);
/* ! an AttributeCode of 0 returns the next free Attribute */
if( (aAttribute=FindClassAttribute( aClass, 0 ))==NULL )
RET(gECIError,-1);
/* ! */
aAttribute->itsAttributeCode = theAttributeCode;
aAttribute->itsIsReadOnly = theIsReadOnly;
aAttribute->itsDataPtr = theDataPtr;
aAttribute->itsDataSize = theDataSize;
/* ! */
RET(ECI_E_SUCCESS,0);
}
int EC_CreateInstanceAttribute( unsigned int theClassCode, unsigned int theInstanceCode, unsigned char theAttributeCode, unsigned int theIsReadOnly, void *theDataPtr, int theDataSize ){
/*
** create a new Attribute in the Instance identified by theClassCode and theInstanceCode
*/
t_Class *aClass;
t_Instance *aInstance;
t_Attribute *aAttribute;
/* ! find Class */
if( (aClass=FindClass( theClassCode ))==NULL )
RET(gECIError,-1);
/* ! find Instance */
if( (aInstance=FindInstance( aClass, theInstanceCode ))==NULL )
RET(gECIError,-1);
/* ! an AttributeCode of 0 returns the next free Attribute */
if( (aAttribute=FindInstanceAttribute( aInstance, 0 ))==NULL )
RET(gECIError,-1);
/* ! */
aAttribute->itsAttributeCode = theAttributeCode;
aAttribute->itsIsReadOnly = theIsReadOnly;
aAttribute->itsDataPtr = theDataPtr;
aAttribute->itsDataSize = theDataSize;
/* ! */
RET(ECI_E_SUCCESS,0);
}
int EC_CheckIntegrity( void ){
/*
** ! test the data consistency of the UserDefined Objects
*/
unsigned int c,ia,ca,i;
t_Class aClass;
t_Instance aInstance;
#define TEST( item, invalid, err ) { if( (item)==(invalid) ) RET((err),-1); }
#define TEST_ATTRIBUTE(a){\
TEST( (a).itsAttributeCode, 0, ECI_E_ATTRIBUTECODE_IS_EMPTY ); \
TEST( (a).itsDataPtr, NULL, ECI_E_DATAPTR_IS_NULL ); \
TEST( (a).itsDataSize, 0, ECI_E_DATASIZE_IS_0 ); \
}
/* ! check the user defined assembly object */
if( gUserDefinedAssembly!=NULL )
for( i=0; i<gUserDefinedAssembly->itsInstancesCount; i++ )
TEST( gUserDefinedAssembly->itsInstances[i].itsInstanceNo, 0, ECI_E_USERDEFINEDASSEMBLY_IS_EMPTY );
/* ! check the user defined objects */
TEST( gUserDefined, NULL, ECI_E_USERDEFINED_IS_NULL );
/* ! */
for( c=0; c<gUserDefined->itsClassesCount; c++ ){
/* ! */
aClass = gUserDefined->itsClasses[c];
TEST( aClass.itsClassCode, 0, ECI_E_CLASSCODE_IS_EMPTY);
/* ! */
for( ca=0; ca<aClass.itsAttributesCount; ca++ ){
/* ! */
TEST_ATTRIBUTE( aClass.itsAttributes[ca] );
/* ! */
for( i=0; i<aClass.itsInstancesCount; i++ ){
/* ! */
aInstance = aClass.itsInstances[i];
TEST( aInstance.itsInstanceCode, 0, ECI_E_INSTANCECODE_IS_EMPTY );
/* ! */
for( ia=0; ia<aInstance.itsAttributesCount; ia++ )
TEST_ATTRIBUTE( aInstance.itsAttributes[ia] );
}
}
}
/* ! */
RET(ECI_E_SUCCESS,0);
}
unsigned int GetAttributeByteSize( t_Attribute *theAttribute ){
/*
** return the size of the attribute data in bytes
*/
/* ! */
return theAttribute->itsDataSize;
}
unsigned int GetClassAttributesByteSize( t_Class *theClass ){
/*
** return the size of all class attribute data in bytes
*/
unsigned int i;
unsigned int aByteSize;
/* ! */
aByteSize = 0;
for(i=0; i<theClass->itsAttributesCount; i++ )
aByteSize += theClass->itsAttributes[i].itsDataSize;
/* ! */
return aByteSize;
}
void GetSetClassAttributes( int thefGet, unsigned char *theBuf, t_Class *theClass ){
/*
** copy all attribute data betweeen the class and the buffer
*/
unsigned int i, aByteSize;
/* ! */
for( i=0; i<theClass->itsAttributesCount; i++ ){
aByteSize = GetAttributeByteSize( &theClass->itsAttributes[i] );
if( thefGet )
memcpy( theBuf, theClass->itsAttributes[i].itsDataPtr, aByteSize );
else
memcpy( theClass->itsAttributes[i].itsDataPtr, theBuf, aByteSize );
theBuf += aByteSize;
}
}
void GetClassAttributes( unsigned char *theBuf, t_Class *theClass ){ GetSetClassAttributes( 1, theBuf, theClass ); }
void SetClassAttributes( unsigned char *theBuf, t_Class *theClass ){ GetSetClassAttributes( 0, theBuf, theClass ); }
unsigned int GetInstanceAttributesByteSize( t_Instance *theInstance ){
/*
** return the size of all instance attribute data in bytes
*/
unsigned int i;
unsigned int aByteSize;
/* ! */
aByteSize = 0;
for(i=0; i<theInstance->itsAttributesCount; i++ )
aByteSize += GetAttributeByteSize( &theInstance->itsAttributes[i] );
/* ! */
return aByteSize;
}
void GetSetInstanceAttributes( int thefGet, unsigned char *theBuf, t_Instance *theInstance ){
/*
** copy all attribute data from the Instance to the buffer
*/
unsigned int i, aByteSize;
/* ! */
for(i=0; i<theInstance->itsAttributesCount; i++ ){
aByteSize = GetAttributeByteSize( &theInstance->itsAttributes[i] );
if( thefGet )
memcpy( theBuf, theInstance->itsAttributes[i].itsDataPtr, aByteSize );
else
memcpy( theInstance->itsAttributes[i].itsDataPtr, theBuf, aByteSize );
theBuf += aByteSize;
}
}
void GetInstanceAttributes( unsigned char *theBuf, t_Instance *theInstance ){ GetSetInstanceAttributes( 1, theBuf, theInstance ); }
void SetInstanceAttributes( unsigned char *theBuf, t_Instance *theInstance ){ GetSetInstanceAttributes( 0, theBuf, theInstance ); }
t_Attribute *GetClassAttribute( t_Class *theClass, unsigned char theAttributeCode ){
/*
** get the attribute of theClasss identified by theAttributeCode
*/
unsigned int i;
/* ! */
for( i=0; i<theClass->itsAttributesCount; i++ )
if( theClass->itsAttributes[i].itsAttributeCode==theAttributeCode )
return &theClass->itsAttributes[i];
/* ! */
return NULL;
}
t_Attribute *GetInstanceAttribute( t_Instance *theInstance, unsigned char theAttributeCode ){
/*
** get the attribute of theInstance identified by theAttributeCode
*/
unsigned int i;
/* ! */
for( i=0; i<theInstance->itsAttributesCount; i++ )
if( theInstance->itsAttributes[i].itsAttributeCode==theAttributeCode )
return &theInstance->itsAttributes[i];
/* ! */
return NULL;
}
/*
** Function to let the user send a Request. Copied from: void en_cd_TxFixedTagPacket(CD_PacketTrrblType * pTrrbl)
*/
extern OE_Q_ID MngOutgoingEncapQueue;
extern ENCAP_OBJ_TARGET list_target_data;
// EXTFUNC ETHERNETIPEXAMPLECODE_API int ListIndentify(void)
// {
//
// UINT16 iSize;
// PKTBUF *msg;
// EnCdMessageType EnCdMessage; /* Message to be sent out via tcpip */
// UINT32 Status;
//
// CB_ComBufType *aCbDestHost;
// CB_ComBufType *aCbData;
//
// /* ! Reset ResponseData */
// gResponseDataSize = 0;
// memset( &gResponseAddrIn, 0, sizeof(gResponseAddrIn));
//
// /*
// ** Message is originating on this board. Allocate message dynamically
// */
// if( ( msg=PktBufAlloc() )==NULL)
// return ECI_E_OUT_OF_MEMORY;
//
// /* ! */
// if( (NULL==(aCbDestHost=CB_NewComBuf( strlen( theHostName ) )) ) )
// return ECI_E_OUT_OF_MEMORY;
//
// /* ! */
// if( (NULL==(aCbData=CB_NewComBuf( theDataLen )) ) )
// {
// CB_DeleteComBuf( aCbDestHost );
// return ECI_E_OUT_OF_MEMORY;
// }
//
//
// /* ! */
// CB_PrependComBuf( aCbDestHost, theHostName, strlen( theHostName ) );
// CB_PrependComBuf( aCbData, theData, theDataLen );
//
//
// /*
// ** Transfer host name in case we need to connect. Send this message on to the management task.
// ** Depending on whether this host has a session set up or not, we may need to do a lot of pre-processing.
// */
//
// EnCdMessage.pcbDestHost = aCbDestHost; /* pTrrbl->pCbDestHost; */
// msg->sOutputQ = MngOutgoingEncapQueue;
//
// /* ! Header */
// msg->sEncap.sHdr.iEncaph_command = ENCAP_CMD_LISTIDENTITY;
// msg->sEncap.sHdr.lEncaph_session = 0;
// msg->sEncap.sHdr.lEncaph_status = 0;
// msg->sEncap.sHdr.lEncaph_opt = 0;
//
// /* ! Data transfer field */
// msg->sEncap.sDt_hdr.lDt_target = 0;
// msg->sEncap.sDt_hdr.iDt_timeout = 0;
// msg->sEncap.lValid = PKTBUF_ENCAPV_DT;
//
// /*
// ** Decided not to save the Cd Packet tribble handle in the context. This would have
// ** required us to save the tribble, and then create some way of recovering the tribbles
// ** should the return message not be sent. Instead we will only save the xUmHandle in the
// ** context and let the UCMM worry about how to handle unreturned responses
// */
// msg->sEncap.sHdr.alEncaph_context[ 1 ] = 0; /* Number, who is not recognized by the EC */
//
// /*
// ** Encode our IP address into the 0 context field. This will help
// ** determine that the incoming message is a reply to us and not an
// ** illegal request from an originator coming in on the wrong socket.
// */
// msg->sEncap.sHdr.alEncaph_context[ 0 ] = list_target_data.sS.s_sock.lSin_addr;
//
// msg->pData = &msg->abData[0]; /* used by en_cd_SetSocketAddresses() */
// msg->lLength = 0; /* used by en_cd_SetSocketAddresses() */
//
//
// /*
// ** setup the SockAddr Info Data types in the packet addenda if needed
// */
// en_cd_SetSocketAddresses( msg, &msg->sEce.sSa );
//
//
// /*
// ** msg should still have the original command, and options (both in host order) in it.
// ** Context is also preserved, though the order was never changed
// */
//
// iSize = CB_GetDataSizeComBuf( aCbData ); /* CB_GetDataSizeComBuf(pTrrbl->pComBuf); */
// msg->sEncap.sPkt_tag.sTag.iTag_length = iSize;
// msg->lLength = iSize;
//
// /*
// ** Instead of copying the data to a new buffer, just attach the combuff and send it to the
// ** transmission task
// */
// msg->pData = aCbData->pData; /* pTrrbl->pComBuf->pData; /* point the datapointer to the combuffer */
// msg->pCb = aCbData; /* pTrrbl->pComBuf; */
// EnCdMessage.Command = SENDCOMMBUF; /* Send the attached message using a combuf */
// EnCdMessage.PacketBuf = msg; /* Tcpip message to be sent. It will be deleted by the send task */
//
// /*
// ** Send to queue the message at the send task, or the management task depending on connection state
// */
// Status = OE_MsgQSend(msg->sOutputQ,
// (char *) &EnCdMessage.Command,
// sizeof EnCdMessage,
// WAIT_FOREVER,
// MSG_PRI_NORMAL);
//
// /*
// ** Send failed, we need to delete the packet here lest we loose it
// */
// if (Status == OE_ERROR)
// {
// CB_DeleteComBuf( aCbDestHost );
// CB_DeleteComBuf( msg->pCb );
// PktBufFree(msg);
// return ECI_E_SEND_SOME_DATA_FAILED;
// }
//
// /* ! */
// return ECI_E_SUCCESS;
//}
EXTFUNC ETHERNETIPEXAMPLECODE_API int EC_Request( char *theHostName, unsigned char *theData, int theDataLen )
{
/*
** Send the CIP Message (theData,theDataLen) to the TCP/IP Address (theHostName)
**
** Example: Get Attribute Single: Class 1, Instance 1, Attribute 1
**
** 02 00 00 00 00 00 B2 00 08 00 0E 03 20 01 24 01 30 06
** | | | | | | | | | 30 06 Loical Segment, Attribute ID, 8-bit
** | | | | | | | | 24 01 Logical Segment, Instance ID, 8-bit
** | | | | | | | 20 01 Logical Segment, Class ID, 8-bit
** | | | | | | 03 Number of 16 bit words in the following Request_Path field
** | | | | | 0E Service Code of the Request: Get Attribute Single
** | | | | 08 00 Item Length in Bytes
** | | | B2 00 Item Code: unconnected message
** | | 00 00 Address Item: Item Length
** | 00 00 Address Item: Item Code
** 02 00 Item Count
*/
UINT16 iSize;
PKTBUF *msg;
EnCdMessageType EnCdMessage; /* Message to be sent out via tcpip */
UINT32 Status;
CB_ComBufType *aCbDestHost;
CB_ComBufType *aCbData;
/* ! Reset ResponseData */
gResponseDataSize = 0;
memset( &gResponseAddrIn, 0, sizeof(gResponseAddrIn));
/*
** Message is originating on this board. Allocate message dynamically
*/
if( ( msg=PktBufAlloc() )==NULL)
return ECI_E_OUT_OF_MEMORY;
/* ! */
if( (NULL==(aCbDestHost=CB_NewComBuf( strlen( theHostName ) )) ) )
return ECI_E_OUT_OF_MEMORY;
/* ! */
if( (NULL==(aCbData=CB_NewComBuf( theDataLen )) ) ){
CB_DeleteComBuf( aCbDestHost );
return ECI_E_OUT_OF_MEMORY;
}
/* ! */
CB_PrependComBuf( aCbDestHost, theHostName, strlen( theHostName ) );
CB_PrependComBuf( aCbData, theData, theDataLen );
/*
** Transfer host name in case we need to connect. Send this message on to the management task.
** Depending on whether this host has a session set up or not, we may need to do a lot of pre-processing.
*/
EnCdMessage.pcbDestHost = aCbDestHost; /* pTrrbl->pCbDestHost; */
msg->sOutputQ = MngOutgoingEncapQueue;
/* ! Header */
msg->sEncap.sHdr.iEncaph_command = ENCAP_CMD_SEND_RRDATA;
msg->sEncap.sHdr.lEncaph_session = 0;
msg->sEncap.sHdr.lEncaph_status = 0;
msg->sEncap.sHdr.lEncaph_opt = 0;
/* ! Data transfer field */
msg->sEncap.sDt_hdr.lDt_target = 0;
msg->sEncap.sDt_hdr.iDt_timeout = 0;
msg->sEncap.lValid = PKTBUF_ENCAPV_DT;
/*
** Decided not to save the Cd Packet tribble handle in the context. This would have
** required us to save the tribble, and then create some way of recovering the tribbles
** should the return message not be sent. Instead we will only save the xUmHandle in the
** context and let the UCMM worry about how to handle unreturned responses
*/
msg->sEncap.sHdr.alEncaph_context[ 1 ] = 0; /* Number, who is not recognized by the EC */
/*
** Encode our IP address into the 0 context field. This will help
** determine that the incoming message is a reply to us and not an
** illegal request from an originator coming in on the wrong socket.
*/
msg->sEncap.sHdr.alEncaph_context[ 0 ] = list_target_data.sS.s_sock.lSin_addr;
msg->pData = &msg->abData[0]; /* used by en_cd_SetSocketAddresses() */
msg->lLength = 0; /* used by en_cd_SetSocketAddresses() */
/*
** setup the SockAddr Info Data types in the packet addenda if needed
*/
en_cd_SetSocketAddresses( msg, &msg->sEce.sSa );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -