/*** BeginHeader MBM_Send_ADU_TCP */
int MBM_Send_ADU_TCP(uint32_t IPAddress, char *Packet, int ByteCount);
#define MMTCP_STATE_WAIT 0
#define MMTCP_STATE_STARTED 1
#define MMTCP_STATE_REMAINDER 2
#define MMTCP_STATE_DONE 3
#define MMTCP_STATE_ERROR 4
/*** EndHeader */
_modbus_dbg
int MBM_Send_ADU_TCP(uint32_t IPAddress, char *Packet, int ByteCount)
{
static tcp_Socket MMSocket;
static far char MMTCPBuffer[1024];
int i;
uint32_t ulTemp;
int16_t iTemp;
int iExpected;
int iMMTState;
int bytes_read;
char cDiscard;
int iResponse;
iResponse = MB_SUCCESS;
#if MODBUS_PRINT
if(cModbusPrintEnabled)
{
printf("Tx TCP:");
for(i=0; i<ByteCount; i++ ) printf ( " %02X", Packet[i]);
printf ( "\n\r" );
}
#endif
if(tcp_extopen(&MMSocket, IF_ETH0, 0, ntohl(IPAddress), 502, NULL, (long)MMTCPBuffer, 1024) != 0)
{
ulTemp = LocalTimeCorrected();
while(0 == sock_established(&MMSocket)) /* Try establish a connection with at most 2 second timeout */
{
if((LocalTimeCorrected() - ulTemp) > 2)
break;
}
if(0 != sock_established(&MMSocket))
{
sock_flushnext(&MMSocket);
iTemp = sock_write(&MMSocket, Packet, ByteCount);
iExpected = MBM_HowMany(&Packet[6]) - 2; // Subtract CRC bytes
ulTemp = LocalTimeCorrected(); // Record when we sent packet
iMMTState = MMTCP_STATE_WAIT;
do
{
if((LocalTimeCorrected() - ulTemp) > 2) // Taking too long...
iMMTState = MMTCP_STATE_ERROR;
switch(iMMTState)
{
case MMTCP_STATE_WAIT:
if(sock_bytesready(&MMSocket) >= 8 ) // Got the minimum expected data so goto next stage
iMMTState = MMTCP_STATE_STARTED;
break;
case MMTCP_STATE_STARTED:
sock_read(&MMSocket, mbADU, 8 ); // Know this will not block as we checked in previous state...
if(mbADU[7] >= 0x80) // Not a good response...
iExpected = 1; // Just the error code to get
else
iExpected -= 2; // Have address and function code...
iMMTState = MMTCP_STATE_REMAINDER;
break;
case MMTCP_STATE_REMAINDER:
if(sock_bytesready(&MMSocket) >= iExpected)
{
sock_read(&MMSocket, &mbADU[8], iExpected);
sock_close(&MMSocket);
while(sock_bytesready(&MMSocket) != -1) // Flush any unread data just in case
{
sock_read(&MMSocket, &cDiscard, 1);
if((LocalTimeCorrected() - ulTemp) > 2) // Taking too long so...
{
sock_abort(&MMSocket);
break;
}
}
iMMTState = MMTCP_STATE_DONE;
}
break;
case MMTCP_STATE_ERROR:
sock_abort(&MMSocket);
return(MBM_PACKET_ERROR);
break;
}
} while(iMMTState != MMTCP_STATE_DONE);
// receive the response into the same buffer used for the transmit data
return(MB_SUCCESS);
}
else
sock_abort(&MMSocket);
}
return(MBM_PACKET_ERROR);
}