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

📄 cm_targt.c

📁 基于EthernetIP协议的应用程序,可以读取AB公司Controllogix系列Ethernetip协议PLC数据. 此软件代码可用于工业控制.
💻 C
📖 第 1 页 / 共 5 页
字号:


            case CI_LOGICAL_SEG_INSTANCE | CI_LOGICAL_SEG_8_BIT:

               /*
               ** 8 bit instance segment.
               */

               psConnRecord->sPublic.iInstance = *( (UINT8*)(pbPath + 1) );
               iSegSize = 1;
               break;

            case CI_LOGICAL_SEG_INSTANCE | CI_LOGICAL_SEG_16_BIT:

               /*
               ** 16 bit instance segment.
               */

               psConnRecord->sPublic.iInstance = UC_iLeTOi( *( (UINT16*)(pbPath + 2) ) );
               iSegSize = 2;
               break;


            default:

               /*
               ** Unknown segment. Force a bail out with an error.
               */

               psConnRecord->sPublic.bGRC = CI_GRC_FAILURE;
               psConnRecord->sPublic.iERC = CM_ERC_BAD_SEGMENT;
               iSegSize = iSize;
               break;
            }

         break;

      case CI_DATA_SEGMENT:

         /*
         ** Data segment.
         */

         psConnRecord->sPublic.bDataSegSize = *(pbPath + 1);
         psConnRecord->sPublic.pLeDataSeg = (void*)(pbPath + 2);
         iSegSize = *(pbPath + 1) + 1;
         break;


      case CI_NETWORK_SEGMENT:
         if( ( CD_s[ psConnRecord->sPublic.iPort ].fUsesScheduleSegs ) && ( !fHaveNetSegment ) )
         {

            /*
            ** The port that this message arrived on can use network segments.
            ** (Must be ControlNet or a similar network.)
            ** So, grab a net-segment to use for producing data on this port.
            */

            fHaveNetSegment = TRUE; /* Only one net-segment is needed, pass others on. */

            switch( *pbPath )
            {
            case CI_NETWORK_SEGMENT | CI_NETWORK_SEG_SCHEDULE:

               /*
               ** Schedule segment.
               ** Unpack the rate and start NUT.
               */

               iSegSize = 1; /*!!NOTE!! Find out why this can't be after cm_UnpackSchedule */

               if( *(pbPath + 1) == 0 )
               {
                  /*
                  ** Invalid Net Segment. Force a bail out with an error.
                  */

                  psConnRecord->sPublic.bGRC = CI_GRC_FAILURE;
                  psConnRecord->sPublic.iERC = CM_ERC_BAD_NET_SEGMENT;
                  iSegSize = iSize;
               }
               else
               {
                  cm_UnpackSchedule( psConnRecord, *(pbPath + 1) );
               }

               break;

#ifdef CD_EN_OBJECTS
            case CI_NETWORK_SEGMENT | CI_NETWORK_SEG_PROD_INHIBIT:

               /*
               ** Production inhibit segment.
               */

               psConnRecord->sPublic.lProInhib = *(pbPath + 1);
               /*
               ** The production inhibit segment is specified in milliseconds, all
               ** other timing is done in microseconds.  Convert it here to
               ** be consistent throughout the EML
               */

               psConnRecord->sPublic.lProInhib *= 1000;
                /* Production inhibit time must be larger than RPI */
               if ( psConnRecord->sPublic.lProApi < psConnRecord->sPublic.lProInhib)
               {
                   psConnRecord->sPublic.bGRC = CI_GRC_FAILURE;
                   psConnRecord->sPublic.iERC = CM_ERC_BAD_RPI;
               }
               iSegSize = iSize;
               break;
#endif
            default:

               /*
               ** Unknown segment. Force a bail out with an error.
               */

               psConnRecord->sPublic.bGRC = CI_GRC_FAILURE;
               psConnRecord->sPublic.iERC = CM_ERC_BAD_SEGMENT;
               iSegSize = iSize;
               break;
            }

            break;


         }
         else

         {

            /*
            ** A Network segment has been detected that
            ** could only be usefull for a bridged message.
            **
            ** However, this device cannot do bridging.
            ** So force a bail out with an error.
            */

            psConnRecord->sPublic.bGRC = CI_GRC_FAILURE;
            psConnRecord->sPublic.iERC = CM_ERC_BAD_SEGMENT;
            iSegSize = iSize;

            break;
         }

      default:

         /*
         ** Unknown segment. Force a bail out with an error.
         */

         psConnRecord->sPublic.bGRC = CI_GRC_FAILURE;
         psConnRecord->sPublic.iERC = CM_ERC_BAD_SEGMENT;
         iSegSize = iSize;
         break;
      }

      /*
      ** Bump the parsing pointer and remaining size counter.
      */

      pbPath += iSegSize << 1;
      iSize  -= iSegSize;
   }

   /*
   ** Done parsing. The remaining size should be 0 (or greater than 0 if bridging).
   ** Complain if it isn't.
   */

   if( iSize < 0 )
   {
      psConnRecord->sPublic.bGRC = CI_GRC_PARTIAL_DATA;
      goto BailOut;
   }

   /*
   ** If port needed a schedule segment, make sure we found one
   */

   if( ( CD_s[ psConnRecord->sPublic.iPort ].fUsesScheduleSegs )
      && ( !fHaveNetSegment )
      && ( ( psConnRecord->sPublic.bClassTrigger & CM_TCT_CLASS_MASK ) == CM_TCT_CLASS_1 )
      && ( !CM_IsConnectionTypeNull( &( psConnRecord->sPublic ) ) ) )
   {
      psConnRecord->sPublic.bGRC = CI_GRC_FAILURE;
      psConnRecord->sPublic.iERC = CM_ERC_BAD_SEGMENT;
      goto BailOut;
   }

   /*
   ** Validate the electronic key if we found one.
   */

   cm_ValidateKey( psConnRecord );

   /*
   ** Initialize the transport related information in the connection record.
   */

BailOut:

   psConnRecord->sPublic.xQid            = GS_NO_QUEUE;
   psConnRecord->sPublic.iConTransportId =
      psConnRecord->sPublic.iProTransportId = 0;


   /*
   ** Shrink the Combuf by the ammount of data consumed.
   **
   ** If not bridging the combuf will look empty.
   ** If bridging, it will contain the remaining path.
   ** In either case, we may still use the data in the comBuf
   ** during the remainder of establishing the connection.
   */

   CB_ShrinkComBuf( pComBuf, ( (iStartingSize - iSize) << 1 ) );

} /* end of cm_ParseFwdOpen() */




/*---------------------------------------------------------------------------
** cm_ProcessAppClose()
**---------------------------------------------------------------------------
*/

void cm_ProcessAppClose( CM_AppOpenCloseTrrblType *pTrrbl )
{
   CB_ComBufType           *pComBuf;
   cm_ConnectionRecordType *psConnRecord;


   /*
   ** Get the connection record pointer & toss the tribble.
   */

   psConnRecord = cm_GetPrivateRecord( pTrrbl->psConnRecord );
   GS_DeleteTrrbl( pTrrbl );

   /*
   ** If the app returned an empty combuf, build a word aligned zero length
   ** data segment in it before going any further.
   */

   if( psConnRecord->pTrrblFC != NULL )
   {
      pComBuf = psConnRecord->pTrrblFC->pComBuf;

      if( ( pComBuf != NULL ) && ( CB_GetDataSizeComBuf( pComBuf ) == 0 ) )
      {
         CB_ClearAndExpandComBuf( pComBuf, 2 );
         *( (UINT16*)CB_GetDataPtrComBuf( pComBuf ) ) = 0;
      }
   }

   /*
   ** Note that we've received the response and continue processing.
   */

   psConnRecord->iSteps |= CM_PS_AC_RETURNED;
   cm_ContinueProcessing( psConnRecord );

} /* end of cm_ProcessAppClose() */



/*---------------------------------------------------------------------------
** cm_ProcessAppOpen()
**---------------------------------------------------------------------------
*/

void cm_ProcessAppOpen( CM_AppOpenCloseTrrblType *pTrrbl )
{
   CB_ComBufType           *pComBuf;
   cm_ConnectionRecordType *psConnRecord;


   /*
   ** Get the connection record pointer and the remains of the forward open.
   */

   psConnRecord = cm_GetPrivateRecord( pTrrbl->psConnRecord );
   pComBuf = pTrrbl->pComBuf;

   /*
   ** If the app returned an empty combuf, build a word aligned zero length
   ** data segment in it before going any further.
   */

   if( ( pComBuf != NULL ) && ( CB_GetDataSizeComBuf( pComBuf ) == 0 ) )
   {
      CB_ClearAndExpandComBuf( pComBuf, 2 );
      *( (UINT16*)CB_GetDataPtrComBuf( pComBuf ) ) = 0;
   }

   /*
   ** If the object doesn't exist or can't accept connections,
   ** put the appropriate status details into the connection record.
   */

   if( pTrrbl->eStatus == MR_UNROUTABLE_PACKET )
   {
      psConnRecord->sPublic.bGRC = CI_GRC_FAILURE;
      psConnRecord->sPublic.iERC = CM_ERC_BAD_SEGMENT;
   }

   if( pTrrbl->eStatus == CM_UNCONNECTABLE_OBJECT )
   {
      psConnRecord->sPublic.bGRC = CI_GRC_FAILURE;
      psConnRecord->sPublic.iERC = CM_ERC_NO_APP_RESOURCES;
   }

   /*
   ** Calculate the connection operating timeout from the API and the
   ** multiplier from the forward open.
   ** Convert the result of that one from microseconds to milliseconds.
   */

   psConnRecord->sPublic.lTimeout = psConnRecord->sPublic.lConApi * ( 4 << psConnRecord->sPublic.bTimeoutMult );
   psConnRecord->sPublic.lTimeout /= 1000L;

   /*
   ** Discard the app open response tribble.
   ** Note that we've received the response.
   ** If there was a problem, bump the processing state so we don't bother
   ** the app object anymore.
   */

   GS_DeleteTrrbl( pTrrbl );
   psConnRecord->iSteps |= CM_PS_AO_RETURNED;

   if( psConnRecord->sPublic.bGRC != CI_GRC_SUCCESS )
   {
      psConnRecord->iSteps |= CM_PS_AOC_ISSUED | CM_PS_AOC_RETURNED | CM_PS_AC_ISSUED | CM_PS_AC_RETURNED;
   }

   /*
   ** Continue processing this connection.
   */

   cm_ContinueProcessing( psConnRecord );

} /* end of cm_ProcessAppOpen() */



/*---------------------------------------------------------------------------
** cm_ProcessAppOpenComplete()
**---------------------------------------------------------------------------
*/

void cm_ProcessAppOpenComplete( CM_AppOpenCloseTrrblType *pTrrbl )
{
   cm_ConnectionRecordType *psConnRecord;


   /*
   ** Grab the stuff of interest from the response tribble & toss it.
   */

   psConnRecord = cm_GetPrivateRecord( pTrrbl->psConnRecord );
   GS_DeleteTrrbl( pTrrbl );

   /*
   ** Note that we've received the response.
   ** Continue processing the connection.
   */

   psConnRecord->iSteps |= CM_PS_AOC_RETURNED;
   cm_ContinueProcessing( psConnRecord );

} /* end of cm_ProcessAppOpenComplete() */



/*---------------------------------------------------------------------------
** cm_ProcessFwdClose()
**---------------------------------------------------------------------------
*/

void cm_ProcessFwdClose( CD_PacketTrrblType *pTrrbl )
{
   cm_ConnectionRecordType  *psConnRecord;
   CB_ComBufType            *pComBuf;
   CM_LeFwdCloseType        *pLeFwdClose;
   UINT8                    *pIOI;
   UINT8                     bGRC;
   UINT16                    iERC;


  /*
   ** Build pointers to the IOI and forward close portions of the packet.
   */

   pComBuf = pTrrbl->pComBuf;
   pIOI = CB_GetDataPtrComBuf( pComBuf );
   pLeFwdClose = (CM_LeFwdCloseType*)( pIOI + CI_IoiPathSize( pComBuf, 0 ) );
   bGRC = CI_GRC_SUCCESS;

   /*
   ** Look for a matching connection.
   */

   psConnRecord = cm_FindConnection( 0,
                                     UC_iLeTOi( pLeFwdClose->iLeOrigVendorId ),
                                     UC_lLeTOl( pLeFwdClose->lLeOrigDeviceSn ),
                                     UC_iLeTOi( pLeFwdClose->iLeOrigConnectionSn ),
                                     pTrrbl->iPort,
                                     0, 0, 0, 0 );
   if( ( psConnRecord == NULL ) || ( psConnRecord->iState & CM_PS_CLOSING ) )
   {
      bGRC = CI_GRC_FAILURE;
      iERC = CM_ERC_BAD_CONNECTION;
   }

   /*
   ** Any errors detected?
   */

   if( bGRC != CI_GRC_SUCCESS )
   {
      /*
      ** Connection not found or already being closed or path bad.
      ** Build the appropriate error reply packet.
      */

      cm_BuildFwdErrorReply( pComBuf,
                             pLeFwdClose->iLeOrigConnectionSn,
                             pLeFwdClose->iLeOrigVendorId,
                             pLeFwdClose->lLeOrigDeviceSn,
                             pLeFwdClose->bClosePathSize,
                             CM_SC_FWD_CLOSE,
                             bGRC,
                             iERC );
      GS_ReturnTrrbl( pTrrbl );
      return;
   }

   /*
   ** Save the remaining path size before changing the Combuf.
   */

   psConnRecord->bRemainingPathSize = pLeFwdClose->bClosePathSize;

   /*
   ** Strip off all of the forward close but the data segment.
   */

   CI_StripIoiPath( pComBuf, 0 );
   CB_ShrinkComBuf( pComBuf, sizeof( CM_LeFwdCloseType ) );

   /*
   ** Save the forward close tribble for future use.
   ** Adjust the connection state & continue processi

⌨️ 快捷键说明

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