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

📄 en_util.c

📁 基于EthernetIP协议的应用程序,可以读取AB公司Controllogix系列Ethernetip协议PLC数据. 此软件代码可用于工业控制.
💻 C
📖 第 1 页 / 共 3 页
字号:
            /*
            ** If we are a bridge, trigger the data send it now.
            */

            if( pTranRec->fBridged )
            {
               /*
               ** First get the sequence count out of the packet and store
               ** it in the transport record.
               ** The ComBuf is shrunk so that only raw data is passes along.
               */

               pTranRec->iLeSeqCount = *( ( UINT16 * ) ( CB_GetDataPtrComBuf( upsTrrbl.Packet->pComBuf ) ) );
               CB_ShrinkComBuf( upsTrrbl.Packet->pComBuf, 2 );

               en_cd_TxClass3Packet( upsTrrbl.Packet, pTranRec );
            }
            else
            {
               /*
               ** Bump the sequence count and mark this data as unverified
               ** if we're a client.
               */

               if( !pTranRec->fServerConsumer )
               {
                  pTranRec->iLeSeqCount++;
                  pTranRec->fVerified = FALSE;
                  upsTrrbl.Packet->iMsgSeq = pTranRec->iLeSeqCount;   /* return seq count to application */
               }
            }
         }
         break;



      default:

         /*
         ** Unsupported request. Pull the plug.
         */

         GS_LogEvent( CD_BAD_TX_TRIBBLE_REQUEST, upsTrrbl.Generic->eRequest, upsTrrbl.Generic, FATAL );
         break;

      }  /* end switch */

      /*
      ** Determine the final disposition of the tribble.
      */

      if( ( upsTrrbl.Generic->xReturnQueue == CD_s[CD_ETHERNET_PORT].xTxUnschedHiQid ) ||
          ( upsTrrbl.Generic->xReturnQueue == CD_s[CD_ETHERNET_PORT].xTxUnschedLoQid ) )
      {
         /*
         ** This was a cleverly routed tribble ( generated by someone else
         ** and "returned" to this task. Toss the tribble now or we get
         ** locked into an infinite loop processing the same tribble.
         */

         GS_DeleteTrrbl( upsTrrbl.Generic );
      }
      else
      {
         /*
         ** Normally routed tribble.
         ** Set completion status in the tribble to whatever is set in
         ** eStatus and then return the tribble to the requestor.
         ** If the tribble is to be deleted, this will happen in the
         ** GS_ReturnTrrbl( ) service when it finds an INVALID message
         ** queue-id in the tribble return Q-Id field.
         */

         upsTrrbl.Generic->eStatus = eStatus;
         GS_ReturnTrrbl( upsTrrbl.Generic );
      }
   }  /* end while */
}  /* end of EN_CD_TxUnscheduledTask( ) */



/****************************************************************************
**
** Private Services
**
*****************************************************************************
*/

/*---------------------------------------------------------------------------
** en_cd_Class1TxPacket( )
**---------------------------------------------------------------------------
*/

void en_cd_Class1TxPacket( UINT8  *pBuf, cd_TransportRecordType * pTranRec )

{
   CPFHDR         *msg;
   struct sockaddr_in sto;
	int ret;

   /*
   ** Allocate a buffer to be used for all the transmitt headers including
   ** the UDP, Ethernet and IP headers.  It will be freed in the stoptransport
   ** call
   */

   msg = (CPFHDR *) pTranRec->pBufB;

   /*
   ** Check to see if the data in the buffer last sent is different
   ** from the new buffer by checking the transport sequence.  IT
   ** IS IMPORTANT to note that unless the sequence count changed
   ** from the last update, data in the send buffer will NOT be
   ** sent per the following if statement.  If you want new data
   ** to be sent regardless of sequence count remove the if statement
   ** below.  THe penalty will be the increased time for the copy operation.
   ** Also see en_cd_PutTransportBuffer.

   ** 02/07/01 jjw Check to see if this is the first buffer to be sent.
   ** if it is then copy the data regaurdless of the serial numbers.
   */
   if ( (*( (UINT16 *) (&msg->iDs_length + 1)) != *((UINT16 *)pBuf) ) ||
        ( pTranRec->iBufState != A_CURRENT_B_FREE ) )
   {
      UC_CopyMem((char *) (&msg->iDs_length + 1), pBuf,
                 pTranRec->iDataSize + 2);   /* throw in the Transport Seq num*/
   }
   /*
   ** We are done using the buffer locked with the GetTransport call.  Unlock
   ** access to it by doing a set semaphore
   */

   GS_SetSemaphore(pTranRec->xSBufAccess);
   /*
   ** pTranRec->iDataSize is the length of the data only.  It does not include the 2 bytes
   ** of transport sequence number.  Do not confuse transport sequence number with
   ** with Common Packet Encapsulation sequence number.  The Common Packet Encapsulation sequence
   ** number is incremented every packet. The transport sequence number is only incremented
   ** when new data is produced
   **/
   *( ( UINT32 * ) msg->aiAs_seq ) = ENCAP_TO_PL( pTranRec->iSeqCount );

   /*
   ** Increment the transmission (Common Packet Encapsulation) count.  This should not be confused with the
   ** transport packet sequence count. Send this message on to
   ** the xmit task. The  connection is already open so we can send it
   ** immediately
   */
   pTranRec->iSeqCount += 1;

   pTranRec->iMsecLastSent = gs_sTimers.sSysTime.iMSecTime;
   sto = pTranRec->sEce.sSa.sTransmit;

   ret = sendto(sClass1Ece.lSockFd,
          (char *) msg,
          sizeof(CPFHDR) + pTranRec->iDataSize + 2,
          0,
          (struct sockaddr *) & sto,
          sizeof(struct sockaddr_in));

}

/*---------------------------------------------------------------------------
** en_cd_TxClass3Packet( )
**---------------------------------------------------------------------------
*/

void en_cd_TxClass3Packet( CD_PacketTrrblType * pTrrbl, cd_TransportRecordType * pTranRec )

{
   typedef packet_struct CI_LeGenTagTranHeaderType2
   {
      UINT8           bSize;
      UINT8           bControl;
      UINT8           bTagPad;
      UINT8           bTag0;
      UINT8           bTag1;
      UINT8           bTag2;
      UINT8           bTag3;
      LeUINT16        iLeSeqCount;
   }
   GNU_PACKED      CI_LeGenTagTranHeaderType2;

   CI_LeGenTagTranHeaderType2 sHeader;
   UINT16          iSize;


   if( pTranRec == NULL )
   {
      return;
   }

   /*
   ** Collect the header information for the packet from the tribble.
   ** This gets loaded into the buffer ahead of the packet.
   ** Include the latest sequence number in the header.
   **
   ** Determine direction based on Transaction record
   */

   if( pTranRec->sEce.sEid.u.type == ECE_TYPE_INBOUND )
      pTrrbl->bRequest = TRUE;
   else
      pTrrbl->bRequest = 0;

   iSize = CB_GetDataSizeComBuf( pTrrbl->pComBuf ) +
      sizeof( CI_LeGenTagTranHeaderType );

   sHeader.bSize = ( ( iSize + 1 ) >> 1 );
   sHeader.bControl = CI_CTRL_TAG_PAD |
      CI_CTRL_ACCEPT_ALWAYS |
      ( ( iSize & 1 ) ? CI_CTRL_DATA_PAD : 0 );
   *( UINT32 * ) & ( sHeader.bTag0 ) = *( UINT32 * ) & pTranRec->abTxTag[0];
   sHeader.iLeSeqCount = pTranRec->iLeSeqCount;

   /*
   ** Call the generic Tx ring buffer load routine with both the packet
   ** and the header we just built.
   */

   en_cd_LoadUnschedTxPacket( ( CD_PacketTrrblType * ) pTrrbl,
                              ( UINT8 * ) ( &sHeader ),
                              pTranRec,
                              sizeof( CI_LeGenTagTranHeaderType2 ),
                              iSize,
                              FALSE );

}  /* end of en_cd_TxClass3Packet */


/*---------------------------------------------------------------------------
** en_cd_ParseClass1Packet( )
**---------------------------------------------------------------------------
*/

UINT32 en_cd_ParseClass1Packet( PKTBUF * psPacketBuf )

{
   UINT32          iCId;
   UINT16          iTagIndex;
   UINT32          iSeqCount;
   UINT16          iTPUSeqCount;
   cd_TransportRecordType *pTagEntry;
   CPFHDR         *msg = ( CPFHDR * ) psPacketBuf->pData;
   UINT32          iTransport;

   GS_UseCritical( );

   if( ( msg->iAs_type == CPF_TAG_ADR_SEQUENCED ) &&   /* connected class 1 */
        ( msg->iAs_length == 8 ) )
   {
      iCId = ENCAP_VALUE_LONG( *(UINT32 *) &msg->aiAs_cid[0] );

      /*
      ** The transport ID might have been assigned by the other node.  It does not necessarily
      ** match our convention.  Therefore, we need to loop through all our transport records to
      ** find the correct transport
      */

/*
** jjw 3/16/01, changed the upper bound to EN_CD_FIRST_C1P_TRANSPORT
*/

      for(iTransport = EN_CD_FIRST_C1C_TRANSPORT; iTransport < EN_CD_FIRST_C1P_TRANSPORT; iTransport++)
      {
          iTagIndex = iTransport - 1;

          pTagEntry = ( CD_s[CD_ETHERNET_PORT].papTransportRecords )[ iTagIndex ];

          /*
          ** Sanity check 1, Make sure we have a valid transport pointer.
          */

          if (pTagEntry == NULL)
          {
             continue;
          }

          /*
          ** Sanity check 2, Make sure transport ID's match
          */

          if( *(UINT32 *)pTagEntry->abRxTag != iCId )
          {
             continue;
          }

          /*
          ** Sanity check 3, Is this being sent by the same IP as opened the connection in the first place ?
          ** Note that this checks Class 1 point to point as well as multicast connections.
          */
          if( pTagEntry->sEce.sAddr.sin_addr.s_addr != psPacketBuf->sEce.sAddr.sin_addr.s_addr )
          {
           continue;
          }

          /*
          ** If we got to here after all the above checks, we have the correct transport.
          */
          break;
      } /* End search through all transports */

      /*
      ** If transport == first class 1 producer, we did not find a match.
      */

      if (iTransport == EN_CD_FIRST_C1P_TRANSPORT)
      {
         return OK;
      }

      /*
      ** Check the Common Packet Encapsulation sequence count.  This count is incremented each time a message is sent out
      **/

      iSeqCount = ENCAP_VALUE_LONG( *( ( UINT32 * ) & msg->aiAs_seq[0] ) );

      /*
      ** First, check to make sure that the Common Packet Encapsulation sequence number is greater than the last received.  This
      ** makes sure that if the packet was routed, etc we do not reuse an old packet.  Also, no assumptions can
      ** be made wrt the first packet serial number, so just check and allow any SN to pass through.
      **
      */

      if( ( IS_GT( iSeqCount, pTagEntry->iSeqCount ) ) ||
          ( pTagEntry->fFirstMessageRcvd == 0) )
      {
         /*
         ** Now that the Common Packet Encapsulation sequence count has been verified lets move on to check the sequence count of the TP
         ** itself.
         **/

         iTPUSeqCount = ENCAP_VALUE_SHORT(*((UINT16 *) ((char *) psPacketBuf->pData + CPFHDR_SIZE ))); /* First word of data is seq count */

         /*
         ** Call the appropriate Rx copy function to copy the I/O data if
         ** the sequence numbers are not the same, OR if this is a bridged transport.
         */

         if( ( iTPUSeqCount != pTagEntry->iLeSeqCount )
             || ( pTagEntry->fFirstMessageRcvd == 0 )
             || ( pTagEntry->fDupNotify )
             || ( pTagEntry->fBridged ) )
         {
            /*
            ** Now get the data information that is appended to this packet
            */

            msg->iDs_type  = ENCAP_TO_HS( msg->iDs_type );
            msg->iDs_length  = ENCAP_TO_HS( msg->iDs_length );

            /*
            ** Several sanity checks here before the copy call.  First, make sure there
            ** is a copy function specified.  Then make sure we have a connected
            ** packet type.  Finally make sure that the length of the received
            ** message is less than the  length specified in the connection, do not trust
            ** that the other end of this connection is going to send what they
            ** promised when they originated.  The length includes the transport
            ** sequence count so subtract 2 off whenever we are figuring out
            ** how much actual data is included. Also make sure that the length
            ** of the complete message agrees with the length of the components.
            */

            if( ( ( UINT32 ) psPacketBuf->lLength != CPFHDR_SIZE + 2 + pTagEntry->iDataSize ) ||
                ( msg->iDs_type != CPF_TAG_PKT_CONNECTED ) ||
                ( msg->iDs_length - 2 > pTagEntry->iDataSize ) )
            {
               pTagEntry->fFirstMessageRcvd = 0;
               return OK;
            }

            if( pTagEntry->pRxCopyFunction != NULL )
            {
               if( ( pTagEntry->pRxCopyFunction )( pTagEntry->xRxAppHandle,
                                                   &iTPUSeqCount,
                                                   (char *) psPacketBuf->pData + CPFHDR_SIZE + 2, /* pointer to actual data */
                                                   (UINT16) (msg->iDs_length - 2) )    /* actual recvd data length */
                           != 0xffff )
               {
                  /*
                  ** Copy the packet sequence number
                  */
                  pTagEntry->iLeSeqCount = iTPUSeqCount;
                  pTagEntry->fFirstMessageRcvd = ~0;  /* No longer first message received */
               }
               else
               {
                  pTagEntry->fFirstMessageRcvd = 0;
               }
            }
            else
            {

               /*
               ** Copy the packet sequence number
               */

⌨️ 快捷键说明

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