| /**************************************************************************** |
| |
| (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 |
| www.systec-electronic.com |
| |
| Project: openPOWERLINK |
| |
| Description: source file for SDO Command Layer module |
| |
| License: |
| |
| Redistribution and use in source and binary forms, with or without |
| modification, are permitted provided that the following conditions |
| are met: |
| |
| 1. Redistributions of source code must retain the above copyright |
| notice, this list of conditions and the following disclaimer. |
| |
| 2. Redistributions in binary form must reproduce the above copyright |
| notice, this list of conditions and the following disclaimer in the |
| documentation and/or other materials provided with the distribution. |
| |
| 3. Neither the name of SYSTEC electronic GmbH nor the names of its |
| contributors may be used to endorse or promote products derived |
| from this software without prior written permission. For written |
| permission, please contact info@systec-electronic.com. |
| |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
| COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
| INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
| BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
| ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| POSSIBILITY OF SUCH DAMAGE. |
| |
| Severability Clause: |
| |
| If a provision of this License is or becomes illegal, invalid or |
| unenforceable in any jurisdiction, that shall not affect: |
| 1. the validity or enforceability in that jurisdiction of any other |
| provision of this License; or |
| 2. the validity or enforceability in other jurisdictions of that or |
| any other provision of this License. |
| |
| ------------------------------------------------------------------------- |
| |
| $RCSfile: EplSdoComu.c,v $ |
| |
| $Author: D.Krueger $ |
| |
| $Revision: 1.14 $ $Date: 2008/10/17 15:32:32 $ |
| |
| $State: Exp $ |
| |
| Build Environment: |
| GCC V3.4 |
| |
| ------------------------------------------------------------------------- |
| |
| Revision History: |
| |
| 2006/06/26 k.t.: start of the implementation |
| |
| ****************************************************************************/ |
| |
| #include "user/EplSdoComu.h" |
| |
| #if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) == 0) &&\ |
| (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) == 0) ) |
| |
| #error 'ERROR: At least SDO Server or SDO Client should be activate!' |
| |
| #endif |
| |
| #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) |
| #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) == 0) && (EPL_OBD_USE_KERNEL == FALSE) |
| |
| #error 'ERROR: SDO Server needs OBDu module!' |
| |
| #endif |
| |
| #endif |
| |
| /***************************************************************************/ |
| /* */ |
| /* */ |
| /* G L O B A L D E F I N I T I O N S */ |
| /* */ |
| /* */ |
| /***************************************************************************/ |
| |
| //--------------------------------------------------------------------------- |
| // const defines |
| //--------------------------------------------------------------------------- |
| |
| #ifndef EPL_MAX_SDO_COM_CON |
| #define EPL_MAX_SDO_COM_CON 5 |
| #endif |
| |
| //--------------------------------------------------------------------------- |
| // local types |
| //--------------------------------------------------------------------------- |
| |
| // intern events |
| typedef enum { |
| kEplSdoComConEventSendFirst = 0x00, // first frame to send |
| kEplSdoComConEventRec = 0x01, // frame received |
| kEplSdoComConEventConEstablished = 0x02, // connection established |
| kEplSdoComConEventConClosed = 0x03, // connection closed |
| kEplSdoComConEventAckReceived = 0x04, // acknowledge received by lower layer |
| // -> continue sending |
| kEplSdoComConEventFrameSended = 0x05, // lower has send a frame |
| kEplSdoComConEventInitError = 0x06, // error duringinitialisiation |
| // of the connection |
| kEplSdoComConEventTimeout = 0x07 // timeout in lower layer |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) |
| , |
| |
| kEplSdoComConEventInitCon = 0x08, // init connection (only client) |
| kEplSdoComConEventAbort = 0x09 // abort sdo transfer (only client) |
| #endif |
| } tEplSdoComConEvent; |
| |
| typedef enum { |
| kEplSdoComSendTypeReq = 0x00, // send a request |
| kEplSdoComSendTypeAckRes = 0x01, // send a resonse without data |
| kEplSdoComSendTypeRes = 0x02, // send response with data |
| kEplSdoComSendTypeAbort = 0x03 // send abort |
| } tEplSdoComSendType; |
| |
| // state of the state maschine |
| typedef enum { |
| // General State |
| kEplSdoComStateIdle = 0x00, // idle state |
| |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) |
| // Server States |
| kEplSdoComStateServerSegmTrans = 0x01, // send following frames |
| #endif |
| |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) |
| // Client States |
| kEplSdoComStateClientWaitInit = 0x10, // wait for init connection |
| // on lower layer |
| kEplSdoComStateClientConnected = 0x11, // connection established |
| kEplSdoComStateClientSegmTrans = 0x12 // send following frames |
| #endif |
| } tEplSdoComState; |
| |
| // control structure for transaction |
| typedef struct { |
| tEplSdoSeqConHdl m_SdoSeqConHdl; // if != 0 -> entry used |
| tEplSdoComState m_SdoComState; |
| u8 m_bTransactionId; |
| unsigned int m_uiNodeId; // NodeId of the target |
| // -> needed to reinit connection |
| // after timeout |
| tEplSdoTransType m_SdoTransType; // Auto, Expedited, Segmented |
| tEplSdoServiceType m_SdoServiceType; // WriteByIndex, ReadByIndex |
| tEplSdoType m_SdoProtType; // protocol layer: Auto, Udp, Asnd, Pdo |
| u8 *m_pData; // pointer to data |
| unsigned int m_uiTransSize; // number of bytes |
| // to transfer |
| unsigned int m_uiTransferredByte; // number of bytes |
| // already transferred |
| tEplSdoFinishedCb m_pfnTransferFinished; // callback function of the |
| // application |
| // -> called in the end of |
| // the SDO transfer |
| void *m_pUserArg; // user definable argument pointer |
| |
| u32 m_dwLastAbortCode; // save the last abort code |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) |
| // only for client |
| unsigned int m_uiTargetIndex; // index to access |
| unsigned int m_uiTargetSubIndex; // subiondex to access |
| |
| // for future use |
| unsigned int m_uiTimeout; // timeout for this connection |
| |
| #endif |
| |
| } tEplSdoComCon; |
| |
| // instance table |
| typedef struct { |
| tEplSdoComCon m_SdoComCon[EPL_MAX_SDO_COM_CON]; |
| |
| #if defined(WIN32) || defined(_WIN32) |
| LPCRITICAL_SECTION m_pCriticalSection; |
| CRITICAL_SECTION m_CriticalSection; |
| #endif |
| |
| } tEplSdoComInstance; |
| |
| //--------------------------------------------------------------------------- |
| // modul globale vars |
| //--------------------------------------------------------------------------- |
| static tEplSdoComInstance SdoComInstance_g; |
| //--------------------------------------------------------------------------- |
| // local function prototypes |
| //--------------------------------------------------------------------------- |
| tEplKernel EplSdoComReceiveCb(tEplSdoSeqConHdl SdoSeqConHdl_p, |
| tEplAsySdoCom *pAsySdoCom_p, |
| unsigned int uiDataSize_p); |
| |
| tEplKernel EplSdoComConCb(tEplSdoSeqConHdl SdoSeqConHdl_p, |
| tEplAsySdoConState AsySdoConState_p); |
| |
| static tEplKernel EplSdoComSearchConIntern(tEplSdoSeqConHdl SdoSeqConHdl_p, |
| tEplSdoComConEvent SdoComConEvent_p, |
| tEplAsySdoCom * pAsySdoCom_p); |
| |
| static tEplKernel EplSdoComProcessIntern(tEplSdoComConHdl SdoComCon_p, |
| tEplSdoComConEvent SdoComConEvent_p, |
| tEplAsySdoCom * pAsySdoCom_p); |
| |
| static tEplKernel EplSdoComTransferFinished(tEplSdoComConHdl SdoComCon_p, |
| tEplSdoComCon * pSdoComCon_p, |
| tEplSdoComConState |
| SdoComConState_p); |
| |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) |
| static tEplKernel EplSdoComServerInitReadByIndex(tEplSdoComCon * pSdoComCon_p, |
| tEplAsySdoCom * pAsySdoCom_p); |
| |
| static tEplKernel EplSdoComServerSendFrameIntern(tEplSdoComCon * pSdoComCon_p, |
| unsigned int uiIndex_p, |
| unsigned int uiSubIndex_p, |
| tEplSdoComSendType SendType_p); |
| |
| static tEplKernel EplSdoComServerInitWriteByIndex(tEplSdoComCon * pSdoComCon_p, |
| tEplAsySdoCom * pAsySdoCom_p); |
| #endif |
| |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) |
| |
| static tEplKernel EplSdoComClientSend(tEplSdoComCon * pSdoComCon_p); |
| |
| static tEplKernel EplSdoComClientProcessFrame(tEplSdoComConHdl SdoComCon_p, |
| tEplAsySdoCom * pAsySdoCom_p); |
| |
| static tEplKernel EplSdoComClientSendAbort(tEplSdoComCon * pSdoComCon_p, |
| u32 dwAbortCode_p); |
| #endif |
| |
| /***************************************************************************/ |
| /* */ |
| /* */ |
| /* C L A S S <SDO Command Layer> */ |
| /* */ |
| /* */ |
| /***************************************************************************/ |
| // |
| // Description: SDO Command layer Modul |
| // |
| // |
| /***************************************************************************/ |
| |
| //=========================================================================// |
| // // |
| // P U B L I C F U N C T I O N S // |
| // // |
| //=========================================================================// |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplSdoComInit |
| // |
| // Description: Init first instance of the module |
| // |
| // |
| // |
| // Parameters: |
| // |
| // |
| // Returns: tEplKernel = errorcode |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| tEplKernel EplSdoComInit(void) |
| { |
| tEplKernel Ret; |
| |
| Ret = EplSdoComAddInstance(); |
| |
| return Ret; |
| |
| } |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplSdoComAddInstance |
| // |
| // Description: Init additional instance of the module |
| // |
| // |
| // |
| // Parameters: |
| // |
| // |
| // Returns: tEplKernel = errorcode |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| tEplKernel EplSdoComAddInstance(void) |
| { |
| tEplKernel Ret; |
| |
| Ret = kEplSuccessful; |
| |
| // init controll structure |
| EPL_MEMSET(&SdoComInstance_g, 0x00, sizeof(SdoComInstance_g)); |
| |
| // init instance of lower layer |
| Ret = EplSdoAsySeqAddInstance(EplSdoComReceiveCb, EplSdoComConCb); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| #if defined(WIN32) || defined(_WIN32) |
| // create critical section for process function |
| SdoComInstance_g.m_pCriticalSection = |
| &SdoComInstance_g.m_CriticalSection; |
| InitializeCriticalSection(SdoComInstance_g.m_pCriticalSection); |
| #endif |
| |
| Exit: |
| return Ret; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplSdoComDelInstance |
| // |
| // Description: delete instance of the module |
| // |
| // |
| // |
| // Parameters: |
| // |
| // |
| // Returns: tEplKernel = errorcode |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| tEplKernel EplSdoComDelInstance(void) |
| { |
| tEplKernel Ret; |
| |
| Ret = kEplSuccessful; |
| |
| #if defined(WIN32) || defined(_WIN32) |
| // delete critical section for process function |
| DeleteCriticalSection(SdoComInstance_g.m_pCriticalSection); |
| #endif |
| |
| Ret = EplSdoAsySeqDelInstance(); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| |
| Exit: |
| return Ret; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplSdoComDefineCon |
| // |
| // Description: function defines a SDO connection to another node |
| // -> init lower layer and returns a handle for the connection. |
| // Two client connections to the same node via the same protocol |
| // are not allowed. If this function detects such a situation |
| // it will return kEplSdoComHandleExists and the handle of |
| // the existing connection in pSdoComConHdl_p. |
| // Using of existing server connections is possible. |
| // |
| // Parameters: pSdoComConHdl_p = pointer to the buffer of the handle |
| // uiTargetNodeId_p = NodeId of the targetnode |
| // ProtType_p = type of protocol to use for connection |
| // |
| // |
| // Returns: tEplKernel = errorcode |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) |
| tEplKernel EplSdoComDefineCon(tEplSdoComConHdl *pSdoComConHdl_p, |
| unsigned int uiTargetNodeId_p, |
| tEplSdoType ProtType_p) |
| { |
| tEplKernel Ret; |
| unsigned int uiCount; |
| unsigned int uiFreeHdl; |
| tEplSdoComCon *pSdoComCon; |
| |
| // check Parameter |
| ASSERT(pSdoComConHdl_p != NULL); |
| |
| // check NodeId |
| if ((uiTargetNodeId_p == EPL_C_ADR_INVALID) |
| || (uiTargetNodeId_p >= EPL_C_ADR_BROADCAST)) { |
| Ret = kEplInvalidNodeId; |
| |
| } |
| // search free control structure |
| pSdoComCon = &SdoComInstance_g.m_SdoComCon[0]; |
| uiCount = 0; |
| uiFreeHdl = EPL_MAX_SDO_COM_CON; |
| while (uiCount < EPL_MAX_SDO_COM_CON) { |
| if (pSdoComCon->m_SdoSeqConHdl == 0) { // free entry |
| uiFreeHdl = uiCount; |
| } else if ((pSdoComCon->m_uiNodeId == uiTargetNodeId_p) |
| && (pSdoComCon->m_SdoProtType == ProtType_p)) { // existing client connection with same node ID and same protocol type |
| *pSdoComConHdl_p = uiCount; |
| Ret = kEplSdoComHandleExists; |
| goto Exit; |
| } |
| uiCount++; |
| pSdoComCon++; |
| } |
| |
| if (uiFreeHdl == EPL_MAX_SDO_COM_CON) { |
| Ret = kEplSdoComNoFreeHandle; |
| goto Exit; |
| } |
| |
| pSdoComCon = &SdoComInstance_g.m_SdoComCon[uiFreeHdl]; |
| // save handle for application |
| *pSdoComConHdl_p = uiFreeHdl; |
| // save parameters |
| pSdoComCon->m_SdoProtType = ProtType_p; |
| pSdoComCon->m_uiNodeId = uiTargetNodeId_p; |
| |
| // set Transaction Id |
| pSdoComCon->m_bTransactionId = 0; |
| |
| // check protocol |
| switch (ProtType_p) { |
| // udp |
| case kEplSdoTypeUdp: |
| { |
| // call connection int function of lower layer |
| Ret = EplSdoAsySeqInitCon(&pSdoComCon->m_SdoSeqConHdl, |
| pSdoComCon->m_uiNodeId, |
| kEplSdoTypeUdp); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| break; |
| } |
| |
| // Asend |
| case kEplSdoTypeAsnd: |
| { |
| // call connection int function of lower layer |
| Ret = EplSdoAsySeqInitCon(&pSdoComCon->m_SdoSeqConHdl, |
| pSdoComCon->m_uiNodeId, |
| kEplSdoTypeAsnd); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| break; |
| } |
| |
| // Pdo -> not supported |
| case kEplSdoTypePdo: |
| default: |
| { |
| Ret = kEplSdoComUnsupportedProt; |
| goto Exit; |
| } |
| } // end of switch(m_ProtType_p) |
| |
| // call process function |
| Ret = EplSdoComProcessIntern(uiFreeHdl, |
| kEplSdoComConEventInitCon, NULL); |
| |
| Exit: |
| return Ret; |
| } |
| #endif |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplSdoComInitTransferByIndex |
| // |
| // Description: function init SDO Transfer for a defined connection |
| // |
| // |
| // |
| // Parameters: SdoComTransParam_p = Structure with parameters for connection |
| // |
| // |
| // Returns: tEplKernel = errorcode |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) |
| tEplKernel EplSdoComInitTransferByIndex(tEplSdoComTransParamByIndex *pSdoComTransParam_p) |
| { |
| tEplKernel Ret; |
| tEplSdoComCon *pSdoComCon; |
| |
| // check parameter |
| if ((pSdoComTransParam_p->m_uiSubindex >= 0xFF) |
| || (pSdoComTransParam_p->m_uiIndex == 0) |
| || (pSdoComTransParam_p->m_uiIndex > 0xFFFF) |
| || (pSdoComTransParam_p->m_pData == NULL) |
| || (pSdoComTransParam_p->m_uiDataSize == 0)) { |
| Ret = kEplSdoComInvalidParam; |
| goto Exit; |
| } |
| |
| if (pSdoComTransParam_p->m_SdoComConHdl >= EPL_MAX_SDO_COM_CON) { |
| Ret = kEplSdoComInvalidHandle; |
| goto Exit; |
| } |
| // get pointer to control structure of connection |
| pSdoComCon = |
| &SdoComInstance_g.m_SdoComCon[pSdoComTransParam_p->m_SdoComConHdl]; |
| |
| // check if handle ok |
| if (pSdoComCon->m_SdoSeqConHdl == 0) { |
| Ret = kEplSdoComInvalidHandle; |
| goto Exit; |
| } |
| // check if command layer is idle |
| if ((pSdoComCon->m_uiTransferredByte + pSdoComCon->m_uiTransSize) > 0) { // handle is not idle |
| Ret = kEplSdoComHandleBusy; |
| goto Exit; |
| } |
| // save parameter |
| // callback function for end of transfer |
| pSdoComCon->m_pfnTransferFinished = |
| pSdoComTransParam_p->m_pfnSdoFinishedCb; |
| pSdoComCon->m_pUserArg = pSdoComTransParam_p->m_pUserArg; |
| |
| // set type of SDO command |
| if (pSdoComTransParam_p->m_SdoAccessType == kEplSdoAccessTypeRead) { |
| pSdoComCon->m_SdoServiceType = kEplSdoServiceReadByIndex; |
| } else { |
| pSdoComCon->m_SdoServiceType = kEplSdoServiceWriteByIndex; |
| |
| } |
| // save pointer to data |
| pSdoComCon->m_pData = pSdoComTransParam_p->m_pData; |
| // maximal bytes to transfer |
| pSdoComCon->m_uiTransSize = pSdoComTransParam_p->m_uiDataSize; |
| // bytes already transfered |
| pSdoComCon->m_uiTransferredByte = 0; |
| |
| // reset parts of control structure |
| pSdoComCon->m_dwLastAbortCode = 0; |
| pSdoComCon->m_SdoTransType = kEplSdoTransAuto; |
| // save timeout |
| //pSdoComCon->m_uiTimeout = SdoComTransParam_p.m_uiTimeout; |
| |
| // save index and subindex |
| pSdoComCon->m_uiTargetIndex = pSdoComTransParam_p->m_uiIndex; |
| pSdoComCon->m_uiTargetSubIndex = pSdoComTransParam_p->m_uiSubindex; |
| |
| // call process function |
| Ret = EplSdoComProcessIntern(pSdoComTransParam_p->m_SdoComConHdl, kEplSdoComConEventSendFirst, // event to start transfer |
| NULL); |
| |
| Exit: |
| return Ret; |
| |
| } |
| #endif |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplSdoComUndefineCon |
| // |
| // Description: function undefine a SDO connection |
| // |
| // |
| // |
| // Parameters: SdoComConHdl_p = handle for the connection |
| // |
| // |
| // Returns: tEplKernel = errorcode |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) |
| tEplKernel EplSdoComUndefineCon(tEplSdoComConHdl SdoComConHdl_p) |
| { |
| tEplKernel Ret; |
| tEplSdoComCon *pSdoComCon; |
| |
| Ret = kEplSuccessful; |
| |
| if (SdoComConHdl_p >= EPL_MAX_SDO_COM_CON) { |
| Ret = kEplSdoComInvalidHandle; |
| goto Exit; |
| } |
| // get pointer to control structure |
| pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComConHdl_p]; |
| |
| // $$$ d.k. abort a running transfer before closing the sequence layer |
| |
| if (((pSdoComCon->m_SdoSeqConHdl & ~EPL_SDO_SEQ_HANDLE_MASK) != |
| EPL_SDO_SEQ_INVALID_HDL) |
| && (pSdoComCon->m_SdoSeqConHdl != 0)) { |
| // close connection in lower layer |
| switch (pSdoComCon->m_SdoProtType) { |
| case kEplSdoTypeAsnd: |
| case kEplSdoTypeUdp: |
| { |
| Ret = |
| EplSdoAsySeqDelCon(pSdoComCon-> |
| m_SdoSeqConHdl); |
| break; |
| } |
| |
| case kEplSdoTypePdo: |
| case kEplSdoTypeAuto: |
| default: |
| { |
| Ret = kEplSdoComUnsupportedProt; |
| goto Exit; |
| } |
| |
| } // end of switch(pSdoComCon->m_SdoProtType) |
| } |
| |
| // clean controll structure |
| EPL_MEMSET(pSdoComCon, 0x00, sizeof(tEplSdoComCon)); |
| Exit: |
| return Ret; |
| } |
| #endif |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplSdoComGetState |
| // |
| // Description: function returns the state fo the connection |
| // |
| // |
| // |
| // Parameters: SdoComConHdl_p = handle for the connection |
| // pSdoComFinished_p = pointer to structur for sdo state |
| // |
| // |
| // Returns: tEplKernel = errorcode |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) |
| tEplKernel EplSdoComGetState(tEplSdoComConHdl SdoComConHdl_p, |
| tEplSdoComFinished *pSdoComFinished_p) |
| { |
| tEplKernel Ret; |
| tEplSdoComCon *pSdoComCon; |
| |
| Ret = kEplSuccessful; |
| |
| if (SdoComConHdl_p >= EPL_MAX_SDO_COM_CON) { |
| Ret = kEplSdoComInvalidHandle; |
| goto Exit; |
| } |
| // get pointer to control structure |
| pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComConHdl_p]; |
| |
| // check if handle ok |
| if (pSdoComCon->m_SdoSeqConHdl == 0) { |
| Ret = kEplSdoComInvalidHandle; |
| goto Exit; |
| } |
| |
| pSdoComFinished_p->m_pUserArg = pSdoComCon->m_pUserArg; |
| pSdoComFinished_p->m_uiNodeId = pSdoComCon->m_uiNodeId; |
| pSdoComFinished_p->m_uiTargetIndex = pSdoComCon->m_uiTargetIndex; |
| pSdoComFinished_p->m_uiTargetSubIndex = pSdoComCon->m_uiTargetSubIndex; |
| pSdoComFinished_p->m_uiTransferredByte = |
| pSdoComCon->m_uiTransferredByte; |
| pSdoComFinished_p->m_dwAbortCode = pSdoComCon->m_dwLastAbortCode; |
| pSdoComFinished_p->m_SdoComConHdl = SdoComConHdl_p; |
| if (pSdoComCon->m_SdoServiceType == kEplSdoServiceWriteByIndex) { |
| pSdoComFinished_p->m_SdoAccessType = kEplSdoAccessTypeWrite; |
| } else { |
| pSdoComFinished_p->m_SdoAccessType = kEplSdoAccessTypeRead; |
| } |
| |
| if (pSdoComCon->m_dwLastAbortCode != 0) { // sdo abort |
| pSdoComFinished_p->m_SdoComConState = |
| kEplSdoComTransferRxAborted; |
| |
| // delete abort code |
| pSdoComCon->m_dwLastAbortCode = 0; |
| |
| } else if ((pSdoComCon->m_SdoSeqConHdl & ~EPL_SDO_SEQ_HANDLE_MASK) == EPL_SDO_SEQ_INVALID_HDL) { // check state |
| pSdoComFinished_p->m_SdoComConState = |
| kEplSdoComTransferLowerLayerAbort; |
| } else if (pSdoComCon->m_SdoComState == kEplSdoComStateClientWaitInit) { |
| // finished |
| pSdoComFinished_p->m_SdoComConState = |
| kEplSdoComTransferNotActive; |
| } else if (pSdoComCon->m_uiTransSize == 0) { // finished |
| pSdoComFinished_p->m_SdoComConState = |
| kEplSdoComTransferFinished; |
| } |
| |
| Exit: |
| return Ret; |
| |
| } |
| #endif |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplSdoComSdoAbort |
| // |
| // Description: function abort a sdo transfer |
| // |
| // |
| // |
| // Parameters: SdoComConHdl_p = handle for the connection |
| // dwAbortCode_p = abort code |
| // |
| // |
| // Returns: tEplKernel = errorcode |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) |
| tEplKernel EplSdoComSdoAbort(tEplSdoComConHdl SdoComConHdl_p, |
| u32 dwAbortCode_p) |
| { |
| tEplKernel Ret; |
| tEplSdoComCon *pSdoComCon; |
| |
| if (SdoComConHdl_p >= EPL_MAX_SDO_COM_CON) { |
| Ret = kEplSdoComInvalidHandle; |
| goto Exit; |
| } |
| // get pointer to control structure of connection |
| pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComConHdl_p]; |
| |
| // check if handle ok |
| if (pSdoComCon->m_SdoSeqConHdl == 0) { |
| Ret = kEplSdoComInvalidHandle; |
| goto Exit; |
| } |
| // save pointer to abort code |
| pSdoComCon->m_pData = (u8 *) & dwAbortCode_p; |
| |
| Ret = EplSdoComProcessIntern(SdoComConHdl_p, |
| kEplSdoComConEventAbort, |
| (tEplAsySdoCom *) NULL); |
| |
| Exit: |
| return Ret; |
| } |
| #endif |
| |
| //=========================================================================// |
| // // |
| // P R I V A T E F U N C T I O N S // |
| // // |
| //=========================================================================// |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplSdoComReceiveCb |
| // |
| // Description: callback function for SDO Sequence Layer |
| // -> indicates new data |
| // |
| // |
| // |
| // Parameters: SdoSeqConHdl_p = Handle for connection |
| // pAsySdoCom_p = pointer to data |
| // uiDataSize_p = size of data ($$$ not used yet, but it should) |
| // |
| // |
| // Returns: |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| tEplKernel EplSdoComReceiveCb(tEplSdoSeqConHdl SdoSeqConHdl_p, |
| tEplAsySdoCom *pAsySdoCom_p, |
| unsigned int uiDataSize_p) |
| { |
| tEplKernel Ret; |
| |
| // search connection internally |
| Ret = EplSdoComSearchConIntern(SdoSeqConHdl_p, |
| kEplSdoComConEventRec, pAsySdoCom_p); |
| |
| EPL_DBGLVL_SDO_TRACE3 |
| ("EplSdoComReceiveCb SdoSeqConHdl: 0x%X, First Byte of pAsySdoCom_p: 0x%02X, uiDataSize_p: 0x%04X\n", |
| SdoSeqConHdl_p, (u16) pAsySdoCom_p->m_le_abCommandData[0], |
| uiDataSize_p); |
| |
| return Ret; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplSdoComConCb |
| // |
| // Description: callback function called by SDO Sequence Layer to inform |
| // command layer about state change of connection |
| // |
| // |
| // |
| // Parameters: SdoSeqConHdl_p = Handle of the connection |
| // AsySdoConState_p = Event of the connection |
| // |
| // |
| // Returns: tEplKernel = Errorcode |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| tEplKernel EplSdoComConCb(tEplSdoSeqConHdl SdoSeqConHdl_p, |
| tEplAsySdoConState AsySdoConState_p) |
| { |
| tEplKernel Ret; |
| tEplSdoComConEvent SdoComConEvent = kEplSdoComConEventSendFirst; |
| |
| Ret = kEplSuccessful; |
| |
| // check state |
| switch (AsySdoConState_p) { |
| case kAsySdoConStateConnected: |
| { |
| EPL_DBGLVL_SDO_TRACE0("Connection established\n"); |
| SdoComConEvent = kEplSdoComConEventConEstablished; |
| // start transmission if needed |
| break; |
| } |
| |
| case kAsySdoConStateInitError: |
| { |
| EPL_DBGLVL_SDO_TRACE0("Error during initialisation\n"); |
| SdoComConEvent = kEplSdoComConEventInitError; |
| // inform app about error and close sequence layer handle |
| break; |
| } |
| |
| case kAsySdoConStateConClosed: |
| { |
| EPL_DBGLVL_SDO_TRACE0("Connection closed\n"); |
| SdoComConEvent = kEplSdoComConEventConClosed; |
| // close sequence layer handle |
| break; |
| } |
| |
| case kAsySdoConStateAckReceived: |
| { |
| EPL_DBGLVL_SDO_TRACE0("Acknowlage received\n"); |
| SdoComConEvent = kEplSdoComConEventAckReceived; |
| // continue transmission |
| break; |
| } |
| |
| case kAsySdoConStateFrameSended: |
| { |
| EPL_DBGLVL_SDO_TRACE0("One Frame sent\n"); |
| SdoComConEvent = kEplSdoComConEventFrameSended; |
| // to continue transmission |
| break; |
| |
| } |
| |
| case kAsySdoConStateTimeout: |
| { |
| EPL_DBGLVL_SDO_TRACE0("Timeout\n"); |
| SdoComConEvent = kEplSdoComConEventTimeout; |
| // close sequence layer handle |
| break; |
| |
| } |
| } // end of switch(AsySdoConState_p) |
| |
| Ret = EplSdoComSearchConIntern(SdoSeqConHdl_p, |
| SdoComConEvent, (tEplAsySdoCom *) NULL); |
| |
| return Ret; |
| } |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplSdoComSearchConIntern |
| // |
| // Description: search a Sdo Sequence Layer connection handle in the |
| // control structure of the Command Layer |
| // |
| // Parameters: SdoSeqConHdl_p = Handle to search |
| // SdoComConEvent_p = event to process |
| // pAsySdoCom_p = pointer to received frame |
| // |
| // Returns: tEplKernel |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| static tEplKernel EplSdoComSearchConIntern(tEplSdoSeqConHdl SdoSeqConHdl_p, |
| tEplSdoComConEvent SdoComConEvent_p, |
| tEplAsySdoCom * pAsySdoCom_p) |
| { |
| tEplKernel Ret; |
| tEplSdoComCon *pSdoComCon; |
| tEplSdoComConHdl HdlCount; |
| tEplSdoComConHdl HdlFree; |
| |
| Ret = kEplSdoComNotResponsible; |
| |
| // get pointer to first element of the array |
| pSdoComCon = &SdoComInstance_g.m_SdoComCon[0]; |
| HdlCount = 0; |
| HdlFree = 0xFFFF; |
| while (HdlCount < EPL_MAX_SDO_COM_CON) { |
| if (pSdoComCon->m_SdoSeqConHdl == SdoSeqConHdl_p) { // matching command layer handle found |
| Ret = EplSdoComProcessIntern(HdlCount, |
| SdoComConEvent_p, |
| pAsySdoCom_p); |
| } else if ((pSdoComCon->m_SdoSeqConHdl == 0) |
| && (HdlFree == 0xFFFF)) { |
| HdlFree = HdlCount; |
| } |
| |
| pSdoComCon++; |
| HdlCount++; |
| } |
| |
| if (Ret == kEplSdoComNotResponsible) { // no responsible command layer handle found |
| if (HdlFree == 0xFFFF) { // no free handle |
| // delete connection immediately |
| // 2008/04/14 m.u./d.k. This connection actually does not exist. |
| // pSdoComCon is invalid. |
| // Ret = EplSdoAsySeqDelCon(pSdoComCon->m_SdoSeqConHdl); |
| Ret = kEplSdoComNoFreeHandle; |
| } else { // create new handle |
| HdlCount = HdlFree; |
| pSdoComCon = &SdoComInstance_g.m_SdoComCon[HdlCount]; |
| pSdoComCon->m_SdoSeqConHdl = SdoSeqConHdl_p; |
| Ret = EplSdoComProcessIntern(HdlCount, |
| SdoComConEvent_p, |
| pAsySdoCom_p); |
| } |
| } |
| |
| return Ret; |
| |
| } |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplSdoComProcessIntern |
| // |
| // Description: search a Sdo Sequence Layer connection handle in the |
| // control structer of the Command Layer |
| // |
| // |
| // |
| // Parameters: SdoComCon_p = index of control structure of connection |
| // SdoComConEvent_p = event to process |
| // pAsySdoCom_p = pointer to received frame |
| // |
| // Returns: tEplKernel = errorcode |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| static tEplKernel EplSdoComProcessIntern(tEplSdoComConHdl SdoComCon_p, |
| tEplSdoComConEvent SdoComConEvent_p, |
| tEplAsySdoCom * pAsySdoCom_p) |
| { |
| tEplKernel Ret; |
| tEplSdoComCon *pSdoComCon; |
| u8 bFlag; |
| |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) |
| u32 dwAbortCode; |
| unsigned int uiSize; |
| #endif |
| |
| #if defined(WIN32) || defined(_WIN32) |
| // enter critical section for process function |
| EnterCriticalSection(SdoComInstance_g.m_pCriticalSection); |
| EPL_DBGLVL_SDO_TRACE0 |
| ("\n\tEnterCiticalSection EplSdoComProcessIntern\n\n"); |
| #endif |
| |
| Ret = kEplSuccessful; |
| |
| // get pointer to control structure |
| pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComCon_p]; |
| |
| // process state maschine |
| switch (pSdoComCon->m_SdoComState) { |
| // idle state |
| case kEplSdoComStateIdle: |
| { |
| // check events |
| switch (SdoComConEvent_p) { |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) |
| // init con for client |
| case kEplSdoComConEventInitCon: |
| { |
| |
| // call of the init function already |
| // processed in EplSdoComDefineCon() |
| // only change state to kEplSdoComStateClientWaitInit |
| pSdoComCon->m_SdoComState = |
| kEplSdoComStateClientWaitInit; |
| break; |
| } |
| #endif |
| |
| // int con for server |
| case kEplSdoComConEventRec: |
| { |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) |
| // check if init of an transfer and no SDO abort |
| if ((pAsySdoCom_p->m_le_bFlags & 0x80) == 0) { // SDO request |
| if ((pAsySdoCom_p->m_le_bFlags & 0x40) == 0) { // no SDO abort |
| // save tansaction id |
| pSdoComCon-> |
| m_bTransactionId = |
| AmiGetByteFromLe |
| (&pAsySdoCom_p-> |
| m_le_bTransactionId); |
| // check command |
| switch (pAsySdoCom_p-> |
| m_le_bCommandId) |
| { |
| case kEplSdoServiceNIL: |
| { // simply acknowlegde NIL command on sequence layer |
| |
| Ret = |
| EplSdoAsySeqSendData |
| (pSdoComCon-> |
| m_SdoSeqConHdl, |
| 0, |
| (tEplFrame |
| *) |
| NULL); |
| |
| break; |
| } |
| |
| case kEplSdoServiceReadByIndex: |
| { // read by index |
| |
| // search entry an start transfer |
| EplSdoComServerInitReadByIndex |
| (pSdoComCon, |
| pAsySdoCom_p); |
| // check next state |
| if (pSdoComCon->m_uiTransSize == 0) { // ready -> stay idle |
| pSdoComCon-> |
| m_SdoComState |
| = |
| kEplSdoComStateIdle; |
| // reset abort code |
| pSdoComCon-> |
| m_dwLastAbortCode |
| = |
| 0; |
| } else { // segmented transfer |
| pSdoComCon-> |
| m_SdoComState |
| = |
| kEplSdoComStateServerSegmTrans; |
| } |
| |
| break; |
| } |
| |
| case kEplSdoServiceWriteByIndex: |
| { |
| |
| // search entry an start write |
| EplSdoComServerInitWriteByIndex |
| (pSdoComCon, |
| pAsySdoCom_p); |
| // check next state |
| if (pSdoComCon->m_uiTransSize == 0) { // already -> stay idle |
| pSdoComCon-> |
| m_SdoComState |
| = |
| kEplSdoComStateIdle; |
| // reset abort code |
| pSdoComCon-> |
| m_dwLastAbortCode |
| = |
| 0; |
| } else { // segmented transfer |
| pSdoComCon-> |
| m_SdoComState |
| = |
| kEplSdoComStateServerSegmTrans; |
| } |
| |
| break; |
| } |
| |
| default: |
| { |
| // unsupported command |
| // -> abort senden |
| dwAbortCode |
| = |
| EPL_SDOAC_UNKNOWN_COMMAND_SPECIFIER; |
| // send abort |
| pSdoComCon-> |
| m_pData |
| = |
| (u8 |
| *) |
| & |
| dwAbortCode; |
| Ret = |
| EplSdoComServerSendFrameIntern |
| (pSdoComCon, |
| 0, |
| 0, |
| kEplSdoComSendTypeAbort); |
| |
| } |
| |
| } // end of switch(pAsySdoCom_p->m_le_bCommandId) |
| } |
| } else { // this command layer handle is not responsible |
| // (wrong direction or wrong transaction ID) |
| Ret = kEplSdoComNotResponsible; |
| goto Exit; |
| } |
| #endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) |
| |
| break; |
| } |
| |
| // connection closed |
| case kEplSdoComConEventInitError: |
| case kEplSdoComConEventTimeout: |
| case kEplSdoComConEventConClosed: |
| { |
| Ret = |
| EplSdoAsySeqDelCon(pSdoComCon-> |
| m_SdoSeqConHdl); |
| // clean control structure |
| EPL_MEMSET(pSdoComCon, 0x00, |
| sizeof(tEplSdoComCon)); |
| break; |
| } |
| |
| default: |
| // d.k. do nothing |
| break; |
| } // end of switch(SdoComConEvent_p) |
| break; |
| } |
| |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) |
| //------------------------------------------------------------------------- |
| // SDO Server part |
| // segmented transfer |
| case kEplSdoComStateServerSegmTrans: |
| { |
| // check events |
| switch (SdoComConEvent_p) { |
| // send next frame |
| case kEplSdoComConEventAckReceived: |
| case kEplSdoComConEventFrameSended: |
| { |
| // check if it is a read |
| if (pSdoComCon->m_SdoServiceType == |
| kEplSdoServiceReadByIndex) { |
| // send next frame |
| EplSdoComServerSendFrameIntern |
| (pSdoComCon, 0, 0, |
| kEplSdoComSendTypeRes); |
| // if all send -> back to idle |
| if (pSdoComCon->m_uiTransSize == 0) { // back to idle |
| pSdoComCon-> |
| m_SdoComState = |
| kEplSdoComStateIdle; |
| // reset abort code |
| pSdoComCon-> |
| m_dwLastAbortCode = |
| 0; |
| } |
| |
| } |
| break; |
| } |
| |
| // process next frame |
| case kEplSdoComConEventRec: |
| { |
| // check if the frame is a SDO response and has the right transaction ID |
| bFlag = |
| AmiGetByteFromLe(&pAsySdoCom_p-> |
| m_le_bFlags); |
| if (((bFlag & 0x80) != 0) |
| && |
| (AmiGetByteFromLe |
| (&pAsySdoCom_p-> |
| m_le_bTransactionId) == |
| pSdoComCon->m_bTransactionId)) { |
| // check if it is a abort |
| if ((bFlag & 0x40) != 0) { // SDO abort |
| // clear control structure |
| pSdoComCon-> |
| m_uiTransSize = 0; |
| pSdoComCon-> |
| m_uiTransferredByte |
| = 0; |
| // change state |
| pSdoComCon-> |
| m_SdoComState = |
| kEplSdoComStateIdle; |
| // reset abort code |
| pSdoComCon-> |
| m_dwLastAbortCode = |
| 0; |
| // d.k.: do not execute anything further on this command |
| break; |
| } |
| // check if it is a write |
| if (pSdoComCon-> |
| m_SdoServiceType == |
| kEplSdoServiceWriteByIndex) |
| { |
| // write data to OD |
| uiSize = |
| AmiGetWordFromLe |
| (&pAsySdoCom_p-> |
| m_le_wSegmentSize); |
| if (pSdoComCon-> |
| m_dwLastAbortCode == |
| 0) { |
| EPL_MEMCPY |
| (pSdoComCon-> |
| m_pData, |
| &pAsySdoCom_p-> |
| m_le_abCommandData |
| [0], |
| uiSize); |
| } |
| // update counter |
| pSdoComCon-> |
| m_uiTransferredByte |
| += uiSize; |
| pSdoComCon-> |
| m_uiTransSize -= |
| uiSize; |
| |
| // update pointer |
| if (pSdoComCon-> |
| m_dwLastAbortCode == |
| 0) { |
| ( /*(u8*) */ |
| pSdoComCon-> |
| m_pData) += |
| uiSize; |
| } |
| // check end of transfer |
| if ((pAsySdoCom_p->m_le_bFlags & 0x30) == 0x30) { // transfer ready |
| pSdoComCon-> |
| m_uiTransSize |
| = 0; |
| |
| if (pSdoComCon-> |
| m_dwLastAbortCode |
| == 0) { |
| // send response |
| // send next frame |
| EplSdoComServerSendFrameIntern |
| (pSdoComCon, |
| 0, |
| 0, |
| kEplSdoComSendTypeRes); |
| // if all send -> back to idle |
| if (pSdoComCon->m_uiTransSize == 0) { // back to idle |
| pSdoComCon-> |
| m_SdoComState |
| = |
| kEplSdoComStateIdle; |
| // reset abort code |
| pSdoComCon-> |
| m_dwLastAbortCode |
| = |
| 0; |
| } |
| } else { // send dabort code |
| // send abort |
| pSdoComCon-> |
| m_pData |
| = |
| (u8 |
| *) |
| & |
| pSdoComCon-> |
| m_dwLastAbortCode; |
| Ret = |
| EplSdoComServerSendFrameIntern |
| (pSdoComCon, |
| 0, |
| 0, |
| kEplSdoComSendTypeAbort); |
| |
| // reset abort code |
| pSdoComCon-> |
| m_dwLastAbortCode |
| = 0; |
| |
| } |
| } else { |
| // send acknowledge without any Command layer data |
| Ret = |
| EplSdoAsySeqSendData |
| (pSdoComCon-> |
| m_SdoSeqConHdl, |
| 0, |
| (tEplFrame |
| *) NULL); |
| } |
| } |
| } else { // this command layer handle is not responsible |
| // (wrong direction or wrong transaction ID) |
| Ret = kEplSdoComNotResponsible; |
| goto Exit; |
| } |
| break; |
| } |
| |
| // connection closed |
| case kEplSdoComConEventInitError: |
| case kEplSdoComConEventTimeout: |
| case kEplSdoComConEventConClosed: |
| { |
| Ret = |
| EplSdoAsySeqDelCon(pSdoComCon-> |
| m_SdoSeqConHdl); |
| // clean control structure |
| EPL_MEMSET(pSdoComCon, 0x00, |
| sizeof(tEplSdoComCon)); |
| break; |
| } |
| |
| default: |
| // d.k. do nothing |
| break; |
| } // end of switch(SdoComConEvent_p) |
| |
| break; |
| } |
| #endif // endif of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) |
| |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) |
| //------------------------------------------------------------------------- |
| // SDO Client part |
| // wait for finish of establishing connection |
| case kEplSdoComStateClientWaitInit: |
| { |
| |
| // if connection handle is invalid reinit connection |
| // d.k.: this will be done only on new events (i.e. InitTransfer) |
| if ((pSdoComCon-> |
| m_SdoSeqConHdl & ~EPL_SDO_SEQ_HANDLE_MASK) == |
| EPL_SDO_SEQ_INVALID_HDL) { |
| // check kind of connection to reinit |
| // check protocol |
| switch (pSdoComCon->m_SdoProtType) { |
| // udp |
| case kEplSdoTypeUdp: |
| { |
| // call connection int function of lower layer |
| Ret = |
| EplSdoAsySeqInitCon |
| (&pSdoComCon-> |
| m_SdoSeqConHdl, |
| pSdoComCon->m_uiNodeId, |
| kEplSdoTypeUdp); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| break; |
| } |
| |
| // Asend -> not supported |
| case kEplSdoTypeAsnd: |
| { |
| // call connection int function of lower layer |
| Ret = |
| EplSdoAsySeqInitCon |
| (&pSdoComCon-> |
| m_SdoSeqConHdl, |
| pSdoComCon->m_uiNodeId, |
| kEplSdoTypeAsnd); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| break; |
| } |
| |
| // Pdo -> not supported |
| case kEplSdoTypePdo: |
| default: |
| { |
| Ret = kEplSdoComUnsupportedProt; |
| goto Exit; |
| } |
| } // end of switch(m_ProtType_p) |
| // d.k.: reset transaction ID, because new sequence layer connection was initialized |
| // $$$ d.k. is this really necessary? |
| //pSdoComCon->m_bTransactionId = 0; |
| } |
| // check events |
| switch (SdoComConEvent_p) { |
| // connection established |
| case kEplSdoComConEventConEstablished: |
| { |
| //send first frame if needed |
| if ((pSdoComCon->m_uiTransSize > 0) |
| && (pSdoComCon->m_uiTargetIndex != 0)) { // start SDO transfer |
| Ret = |
| EplSdoComClientSend |
| (pSdoComCon); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| // check if segemted transfer |
| if (pSdoComCon-> |
| m_SdoTransType == |
| kEplSdoTransSegmented) { |
| pSdoComCon-> |
| m_SdoComState = |
| kEplSdoComStateClientSegmTrans; |
| goto Exit; |
| } |
| } |
| // goto state kEplSdoComStateClientConnected |
| pSdoComCon->m_SdoComState = |
| kEplSdoComStateClientConnected; |
| goto Exit; |
| } |
| |
| case kEplSdoComConEventSendFirst: |
| { |
| // infos for transfer already saved by function EplSdoComInitTransferByIndex |
| break; |
| } |
| |
| case kEplSdoComConEventConClosed: |
| case kEplSdoComConEventInitError: |
| case kEplSdoComConEventTimeout: |
| { |
| // close sequence layer handle |
| Ret = |
| EplSdoAsySeqDelCon(pSdoComCon-> |
| m_SdoSeqConHdl); |
| pSdoComCon->m_SdoSeqConHdl |= |
| EPL_SDO_SEQ_INVALID_HDL; |
| // call callback function |
| if (SdoComConEvent_p == |
| kEplSdoComConEventTimeout) { |
| pSdoComCon->m_dwLastAbortCode = |
| EPL_SDOAC_TIME_OUT; |
| } else { |
| pSdoComCon->m_dwLastAbortCode = |
| 0; |
| } |
| Ret = |
| EplSdoComTransferFinished |
| (SdoComCon_p, pSdoComCon, |
| kEplSdoComTransferLowerLayerAbort); |
| // d.k.: do not clean control structure |
| break; |
| } |
| |
| default: |
| // d.k. do nothing |
| break; |
| |
| } // end of switch(SdoComConEvent_p) |
| break; |
| } |
| |
| // connected |
| case kEplSdoComStateClientConnected: |
| { |
| // check events |
| switch (SdoComConEvent_p) { |
| // send a frame |
| case kEplSdoComConEventSendFirst: |
| case kEplSdoComConEventAckReceived: |
| case kEplSdoComConEventFrameSended: |
| { |
| Ret = EplSdoComClientSend(pSdoComCon); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| // check if read transfer finished |
| if ((pSdoComCon->m_uiTransSize == 0) |
| && (pSdoComCon-> |
| m_uiTransferredByte != 0) |
| && (pSdoComCon->m_SdoServiceType == |
| kEplSdoServiceReadByIndex)) { |
| // inc transaction id |
| pSdoComCon->m_bTransactionId++; |
| // call callback of application |
| pSdoComCon->m_dwLastAbortCode = |
| 0; |
| Ret = |
| EplSdoComTransferFinished |
| (SdoComCon_p, pSdoComCon, |
| kEplSdoComTransferFinished); |
| |
| goto Exit; |
| } |
| // check if segemted transfer |
| if (pSdoComCon->m_SdoTransType == |
| kEplSdoTransSegmented) { |
| pSdoComCon->m_SdoComState = |
| kEplSdoComStateClientSegmTrans; |
| goto Exit; |
| } |
| break; |
| } |
| |
| // frame received |
| case kEplSdoComConEventRec: |
| { |
| // check if the frame is a SDO response and has the right transaction ID |
| bFlag = |
| AmiGetByteFromLe(&pAsySdoCom_p-> |
| m_le_bFlags); |
| if (((bFlag & 0x80) != 0) |
| && |
| (AmiGetByteFromLe |
| (&pAsySdoCom_p-> |
| m_le_bTransactionId) == |
| pSdoComCon->m_bTransactionId)) { |
| // check if abort or not |
| if ((bFlag & 0x40) != 0) { |
| // send acknowledge without any Command layer data |
| Ret = |
| EplSdoAsySeqSendData |
| (pSdoComCon-> |
| m_SdoSeqConHdl, 0, |
| (tEplFrame *) |
| NULL); |
| // inc transaction id |
| pSdoComCon-> |
| m_bTransactionId++; |
| // save abort code |
| pSdoComCon-> |
| m_dwLastAbortCode = |
| AmiGetDwordFromLe |
| (&pAsySdoCom_p-> |
| m_le_abCommandData |
| [0]); |
| // call callback of application |
| Ret = |
| EplSdoComTransferFinished |
| (SdoComCon_p, |
| pSdoComCon, |
| kEplSdoComTransferRxAborted); |
| |
| goto Exit; |
| } else { // normal frame received |
| // check frame |
| Ret = |
| EplSdoComClientProcessFrame |
| (SdoComCon_p, |
| pAsySdoCom_p); |
| |
| // check if transfer ready |
| if (pSdoComCon-> |
| m_uiTransSize == |
| 0) { |
| // send acknowledge without any Command layer data |
| Ret = |
| EplSdoAsySeqSendData |
| (pSdoComCon-> |
| m_SdoSeqConHdl, |
| 0, |
| (tEplFrame |
| *) NULL); |
| // inc transaction id |
| pSdoComCon-> |
| m_bTransactionId++; |
| // call callback of application |
| pSdoComCon-> |
| m_dwLastAbortCode |
| = 0; |
| Ret = |
| EplSdoComTransferFinished |
| (SdoComCon_p, |
| pSdoComCon, |
| kEplSdoComTransferFinished); |
| |
| goto Exit; |
| } |
| |
| } |
| } else { // this command layer handle is not responsible |
| // (wrong direction or wrong transaction ID) |
| Ret = kEplSdoComNotResponsible; |
| goto Exit; |
| } |
| break; |
| } |
| |
| // connection closed event go back to kEplSdoComStateClientWaitInit |
| case kEplSdoComConEventConClosed: |
| { // connection closed by communication partner |
| // close sequence layer handle |
| Ret = |
| EplSdoAsySeqDelCon(pSdoComCon-> |
| m_SdoSeqConHdl); |
| // set handle to invalid and enter kEplSdoComStateClientWaitInit |
| pSdoComCon->m_SdoSeqConHdl |= |
| EPL_SDO_SEQ_INVALID_HDL; |
| // change state |
| pSdoComCon->m_SdoComState = |
| kEplSdoComStateClientWaitInit; |
| |
| // call callback of application |
| pSdoComCon->m_dwLastAbortCode = 0; |
| Ret = |
| EplSdoComTransferFinished |
| (SdoComCon_p, pSdoComCon, |
| kEplSdoComTransferLowerLayerAbort); |
| |
| goto Exit; |
| |
| break; |
| } |
| |
| // abort to send from higher layer |
| case kEplSdoComConEventAbort: |
| { |
| EplSdoComClientSendAbort(pSdoComCon, |
| *((u32 *) |
| pSdoComCon-> |
| m_pData)); |
| |
| // inc transaction id |
| pSdoComCon->m_bTransactionId++; |
| // call callback of application |
| pSdoComCon->m_dwLastAbortCode = |
| *((u32 *) pSdoComCon->m_pData); |
| Ret = |
| EplSdoComTransferFinished |
| (SdoComCon_p, pSdoComCon, |
| kEplSdoComTransferTxAborted); |
| |
| break; |
| } |
| |
| case kEplSdoComConEventInitError: |
| case kEplSdoComConEventTimeout: |
| { |
| // close sequence layer handle |
| Ret = |
| EplSdoAsySeqDelCon(pSdoComCon-> |
| m_SdoSeqConHdl); |
| pSdoComCon->m_SdoSeqConHdl |= |
| EPL_SDO_SEQ_INVALID_HDL; |
| // change state |
| pSdoComCon->m_SdoComState = |
| kEplSdoComStateClientWaitInit; |
| // call callback of application |
| pSdoComCon->m_dwLastAbortCode = |
| EPL_SDOAC_TIME_OUT; |
| Ret = |
| EplSdoComTransferFinished |
| (SdoComCon_p, pSdoComCon, |
| kEplSdoComTransferLowerLayerAbort); |
| |
| } |
| |
| default: |
| // d.k. do nothing |
| break; |
| |
| } // end of switch(SdoComConEvent_p) |
| |
| break; |
| } |
| |
| // process segmented transfer |
| case kEplSdoComStateClientSegmTrans: |
| { |
| // check events |
| switch (SdoComConEvent_p) { |
| // sned a frame |
| case kEplSdoComConEventSendFirst: |
| case kEplSdoComConEventAckReceived: |
| case kEplSdoComConEventFrameSended: |
| { |
| Ret = EplSdoComClientSend(pSdoComCon); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| // check if read transfer finished |
| if ((pSdoComCon->m_uiTransSize == 0) |
| && (pSdoComCon->m_SdoServiceType == |
| kEplSdoServiceReadByIndex)) { |
| // inc transaction id |
| pSdoComCon->m_bTransactionId++; |
| // change state |
| pSdoComCon->m_SdoComState = |
| kEplSdoComStateClientConnected; |
| // call callback of application |
| pSdoComCon->m_dwLastAbortCode = |
| 0; |
| Ret = |
| EplSdoComTransferFinished |
| (SdoComCon_p, pSdoComCon, |
| kEplSdoComTransferFinished); |
| |
| goto Exit; |
| } |
| |
| break; |
| } |
| |
| // frame received |
| case kEplSdoComConEventRec: |
| { |
| // check if the frame is a response |
| bFlag = |
| AmiGetByteFromLe(&pAsySdoCom_p-> |
| m_le_bFlags); |
| if (((bFlag & 0x80) != 0) |
| && |
| (AmiGetByteFromLe |
| (&pAsySdoCom_p-> |
| m_le_bTransactionId) == |
| pSdoComCon->m_bTransactionId)) { |
| // check if abort or not |
| if ((bFlag & 0x40) != 0) { |
| // send acknowledge without any Command layer data |
| Ret = |
| EplSdoAsySeqSendData |
| (pSdoComCon-> |
| m_SdoSeqConHdl, 0, |
| (tEplFrame *) |
| NULL); |
| // inc transaction id |
| pSdoComCon-> |
| m_bTransactionId++; |
| // change state |
| pSdoComCon-> |
| m_SdoComState = |
| kEplSdoComStateClientConnected; |
| // save abort code |
| pSdoComCon-> |
| m_dwLastAbortCode = |
| AmiGetDwordFromLe |
| (&pAsySdoCom_p-> |
| m_le_abCommandData |
| [0]); |
| // call callback of application |
| Ret = |
| EplSdoComTransferFinished |
| (SdoComCon_p, |
| pSdoComCon, |
| kEplSdoComTransferRxAborted); |
| |
| goto Exit; |
| } else { // normal frame received |
| // check frame |
| Ret = |
| EplSdoComClientProcessFrame |
| (SdoComCon_p, |
| pAsySdoCom_p); |
| |
| // check if transfer ready |
| if (pSdoComCon-> |
| m_uiTransSize == |
| 0) { |
| // send acknowledge without any Command layer data |
| Ret = |
| EplSdoAsySeqSendData |
| (pSdoComCon-> |
| m_SdoSeqConHdl, |
| 0, |
| (tEplFrame |
| *) NULL); |
| // inc transaction id |
| pSdoComCon-> |
| m_bTransactionId++; |
| // change state |
| pSdoComCon-> |
| m_SdoComState |
| = |
| kEplSdoComStateClientConnected; |
| // call callback of application |
| pSdoComCon-> |
| m_dwLastAbortCode |
| = 0; |
| Ret = |
| EplSdoComTransferFinished |
| (SdoComCon_p, |
| pSdoComCon, |
| kEplSdoComTransferFinished); |
| |
| } |
| |
| } |
| } |
| break; |
| } |
| |
| // connection closed event go back to kEplSdoComStateClientWaitInit |
| case kEplSdoComConEventConClosed: |
| { // connection closed by communication partner |
| // close sequence layer handle |
| Ret = |
| EplSdoAsySeqDelCon(pSdoComCon-> |
| m_SdoSeqConHdl); |
| // set handle to invalid and enter kEplSdoComStateClientWaitInit |
| pSdoComCon->m_SdoSeqConHdl |= |
| EPL_SDO_SEQ_INVALID_HDL; |
| // change state |
| pSdoComCon->m_SdoComState = |
| kEplSdoComStateClientWaitInit; |
| // inc transaction id |
| pSdoComCon->m_bTransactionId++; |
| // call callback of application |
| pSdoComCon->m_dwLastAbortCode = 0; |
| Ret = |
| EplSdoComTransferFinished |
| (SdoComCon_p, pSdoComCon, |
| kEplSdoComTransferFinished); |
| |
| break; |
| } |
| |
| // abort to send from higher layer |
| case kEplSdoComConEventAbort: |
| { |
| EplSdoComClientSendAbort(pSdoComCon, |
| *((u32 *) |
| pSdoComCon-> |
| m_pData)); |
| |
| // inc transaction id |
| pSdoComCon->m_bTransactionId++; |
| // change state |
| pSdoComCon->m_SdoComState = |
| kEplSdoComStateClientConnected; |
| // call callback of application |
| pSdoComCon->m_dwLastAbortCode = |
| *((u32 *) pSdoComCon->m_pData); |
| Ret = |
| EplSdoComTransferFinished |
| (SdoComCon_p, pSdoComCon, |
| kEplSdoComTransferTxAborted); |
| |
| break; |
| } |
| |
| case kEplSdoComConEventInitError: |
| case kEplSdoComConEventTimeout: |
| { |
| // close sequence layer handle |
| Ret = |
| EplSdoAsySeqDelCon(pSdoComCon-> |
| m_SdoSeqConHdl); |
| pSdoComCon->m_SdoSeqConHdl |= |
| EPL_SDO_SEQ_INVALID_HDL; |
| // change state |
| pSdoComCon->m_SdoComState = |
| kEplSdoComStateClientWaitInit; |
| // call callback of application |
| pSdoComCon->m_dwLastAbortCode = |
| EPL_SDOAC_TIME_OUT; |
| Ret = |
| EplSdoComTransferFinished |
| (SdoComCon_p, pSdoComCon, |
| kEplSdoComTransferLowerLayerAbort); |
| |
| } |
| |
| default: |
| // d.k. do nothing |
| break; |
| |
| } // end of switch(SdoComConEvent_p) |
| |
| break; |
| } |
| #endif // endo of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) |
| |
| } // end of switch(pSdoComCon->m_SdoComState) |
| |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) |
| Exit: |
| #endif |
| |
| #if defined(WIN32) || defined(_WIN32) |
| // leave critical section for process function |
| EPL_DBGLVL_SDO_TRACE0 |
| ("\n\tLeaveCriticalSection EplSdoComProcessIntern\n\n"); |
| LeaveCriticalSection(SdoComInstance_g.m_pCriticalSection); |
| |
| #endif |
| |
| return Ret; |
| |
| } |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplSdoComServerInitReadByIndex |
| // |
| // Description: function start the processing of an read by index command |
| // |
| // |
| // |
| // Parameters: pSdoComCon_p = pointer to control structure of connection |
| // pAsySdoCom_p = pointer to received frame |
| // |
| // Returns: tEplKernel = errorcode |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) |
| static tEplKernel EplSdoComServerInitReadByIndex(tEplSdoComCon * pSdoComCon_p, |
| tEplAsySdoCom * pAsySdoCom_p) |
| { |
| tEplKernel Ret; |
| unsigned int uiIndex; |
| unsigned int uiSubindex; |
| tEplObdSize EntrySize; |
| tEplObdAccess AccessType; |
| u32 dwAbortCode; |
| |
| dwAbortCode = 0; |
| |
| // a init of a read could not be a segmented transfer |
| // -> no variable part of header |
| |
| // get index and subindex |
| uiIndex = AmiGetWordFromLe(&pAsySdoCom_p->m_le_abCommandData[0]); |
| uiSubindex = AmiGetByteFromLe(&pAsySdoCom_p->m_le_abCommandData[2]); |
| |
| // check accesstype of entry |
| // existens of entry |
| //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) |
| Ret = EplObduGetAccessType(uiIndex, uiSubindex, &AccessType); |
| /*#else |
| Ret = kEplObdSubindexNotExist; |
| AccessType = 0; |
| #endif*/ |
| if (Ret == kEplObdSubindexNotExist) { // subentry doesn't exist |
| dwAbortCode = EPL_SDOAC_SUB_INDEX_NOT_EXIST; |
| // send abort |
| pSdoComCon_p->m_pData = (u8 *) & dwAbortCode; |
| Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, |
| uiIndex, |
| uiSubindex, |
| kEplSdoComSendTypeAbort); |
| goto Exit; |
| } else if (Ret != kEplSuccessful) { // entry doesn't exist |
| dwAbortCode = EPL_SDOAC_OBJECT_NOT_EXIST; |
| // send abort |
| pSdoComCon_p->m_pData = (u8 *) & dwAbortCode; |
| Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, |
| uiIndex, |
| uiSubindex, |
| kEplSdoComSendTypeAbort); |
| goto Exit; |
| } |
| // compare accesstype must be read or const |
| if (((AccessType & kEplObdAccRead) == 0) |
| && ((AccessType & kEplObdAccConst) == 0)) { |
| |
| if ((AccessType & kEplObdAccWrite) != 0) { |
| // entry read a write only object |
| dwAbortCode = EPL_SDOAC_READ_TO_WRITE_ONLY_OBJ; |
| } else { |
| dwAbortCode = EPL_SDOAC_UNSUPPORTED_ACCESS; |
| } |
| // send abort |
| pSdoComCon_p->m_pData = (u8 *) & dwAbortCode; |
| Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, |
| uiIndex, |
| uiSubindex, |
| kEplSdoComSendTypeAbort); |
| goto Exit; |
| } |
| // save service |
| pSdoComCon_p->m_SdoServiceType = kEplSdoServiceReadByIndex; |
| |
| // get size of object to see iof segmented or expedited transfer |
| //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) |
| EntrySize = EplObduGetDataSize(uiIndex, uiSubindex); |
| /*#else |
| EntrySize = 0; |
| #endif*/ |
| if (EntrySize > EPL_SDO_MAX_PAYLOAD) { // segmented transfer |
| pSdoComCon_p->m_SdoTransType = kEplSdoTransSegmented; |
| // get pointer to object-entry data |
| //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) |
| pSdoComCon_p->m_pData = |
| EplObduGetObjectDataPtr(uiIndex, uiSubindex); |
| //#endif |
| } else { // expedited transfer |
| pSdoComCon_p->m_SdoTransType = kEplSdoTransExpedited; |
| } |
| |
| pSdoComCon_p->m_uiTransSize = EntrySize; |
| pSdoComCon_p->m_uiTransferredByte = 0; |
| |
| Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, |
| uiIndex, |
| uiSubindex, kEplSdoComSendTypeRes); |
| if (Ret != kEplSuccessful) { |
| // error -> abort |
| dwAbortCode = EPL_SDOAC_GENERAL_ERROR; |
| // send abort |
| pSdoComCon_p->m_pData = (u8 *) & dwAbortCode; |
| Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, |
| uiIndex, |
| uiSubindex, |
| kEplSdoComSendTypeAbort); |
| goto Exit; |
| } |
| |
| Exit: |
| return Ret; |
| } |
| #endif |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplSdoComServerSendFrameIntern(); |
| // |
| // Description: function creats and send a frame for server |
| // |
| // |
| // |
| // Parameters: pSdoComCon_p = pointer to control structure of connection |
| // uiIndex_p = index to send if expedited transfer else 0 |
| // uiSubIndex_p = subindex to send if expedited transfer else 0 |
| // SendType_p = to of frame to send |
| // |
| // Returns: tEplKernel = errorcode |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) |
| static tEplKernel EplSdoComServerSendFrameIntern(tEplSdoComCon * pSdoComCon_p, |
| unsigned int uiIndex_p, |
| unsigned int uiSubIndex_p, |
| tEplSdoComSendType SendType_p) |
| { |
| tEplKernel Ret; |
| u8 abFrame[EPL_MAX_SDO_FRAME_SIZE]; |
| tEplFrame *pFrame; |
| tEplAsySdoCom *pCommandFrame; |
| unsigned int uiSizeOfFrame; |
| u8 bFlag; |
| |
| Ret = kEplSuccessful; |
| |
| pFrame = (tEplFrame *) & abFrame[0]; |
| |
| EPL_MEMSET(&abFrame[0], 0x00, sizeof(abFrame)); |
| |
| // build generic part of frame |
| // get pointer to command layerpart of frame |
| pCommandFrame = |
| &pFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame. |
| m_le_abSdoSeqPayload; |
| AmiSetByteToLe(&pCommandFrame->m_le_bCommandId, |
| pSdoComCon_p->m_SdoServiceType); |
| AmiSetByteToLe(&pCommandFrame->m_le_bTransactionId, |
| pSdoComCon_p->m_bTransactionId); |
| |
| // set size to header size |
| uiSizeOfFrame = 8; |
| |
| // check SendType |
| switch (SendType_p) { |
| // requestframe to send |
| case kEplSdoComSendTypeReq: |
| { |
| // nothing to do for server |
| //-> error |
| Ret = kEplSdoComInvalidSendType; |
| break; |
| } |
| |
| // response without data to send |
| case kEplSdoComSendTypeAckRes: |
| { |
| // set response flag |
| AmiSetByteToLe(&pCommandFrame->m_le_bFlags, 0x80); |
| |
| // send frame |
| Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl, |
| uiSizeOfFrame, pFrame); |
| |
| break; |
| } |
| |
| // responsframe to send |
| case kEplSdoComSendTypeRes: |
| { |
| // set response flag |
| bFlag = AmiGetByteFromLe(&pCommandFrame->m_le_bFlags); |
| bFlag |= 0x80; |
| AmiSetByteToLe(&pCommandFrame->m_le_bFlags, bFlag); |
| |
| // check type of resonse |
| if (pSdoComCon_p->m_SdoTransType == kEplSdoTransExpedited) { // Expedited transfer |
| // copy data in frame |
| //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) |
| Ret = EplObduReadEntryToLe(uiIndex_p, |
| uiSubIndex_p, |
| &pCommandFrame-> |
| m_le_abCommandData |
| [0], |
| (tEplObdSize *) & |
| pSdoComCon_p-> |
| m_uiTransSize); |
| if (Ret != kEplSuccessful) { |
| goto Exit; |
| } |
| //#endif |
| |
| // set size of frame |
| AmiSetWordToLe(&pCommandFrame-> |
| m_le_wSegmentSize, |
| (u16) pSdoComCon_p-> |
| m_uiTransSize); |
| |
| // correct byte-counter |
| uiSizeOfFrame += pSdoComCon_p->m_uiTransSize; |
| pSdoComCon_p->m_uiTransferredByte += |
| pSdoComCon_p->m_uiTransSize; |
| pSdoComCon_p->m_uiTransSize = 0; |
| |
| // send frame |
| uiSizeOfFrame += pSdoComCon_p->m_uiTransSize; |
| Ret = |
| EplSdoAsySeqSendData(pSdoComCon_p-> |
| m_SdoSeqConHdl, |
| uiSizeOfFrame, pFrame); |
| } else if (pSdoComCon_p->m_SdoTransType == kEplSdoTransSegmented) { // segmented transfer |
| // distinguish between init, segment and complete |
| if (pSdoComCon_p->m_uiTransferredByte == 0) { // init |
| // set init flag |
| bFlag = |
| AmiGetByteFromLe(&pCommandFrame-> |
| m_le_bFlags); |
| bFlag |= 0x10; |
| AmiSetByteToLe(&pCommandFrame-> |
| m_le_bFlags, bFlag); |
| // init variable header |
| AmiSetDwordToLe(&pCommandFrame-> |
| m_le_abCommandData[0], |
| pSdoComCon_p-> |
| m_uiTransSize); |
| // copy data in frame |
| EPL_MEMCPY(&pCommandFrame-> |
| m_le_abCommandData[4], |
| pSdoComCon_p->m_pData, |
| (EPL_SDO_MAX_PAYLOAD - 4)); |
| |
| // correct byte-counter |
| pSdoComCon_p->m_uiTransSize -= |
| (EPL_SDO_MAX_PAYLOAD - 4); |
| pSdoComCon_p->m_uiTransferredByte += |
| (EPL_SDO_MAX_PAYLOAD - 4); |
| // move data pointer |
| pSdoComCon_p->m_pData += |
| (EPL_SDO_MAX_PAYLOAD - 4); |
| |
| // set segment size |
| AmiSetWordToLe(&pCommandFrame-> |
| m_le_wSegmentSize, |
| (EPL_SDO_MAX_PAYLOAD - |
| 4)); |
| |
| // send frame |
| uiSizeOfFrame += EPL_SDO_MAX_PAYLOAD; |
| Ret = |
| EplSdoAsySeqSendData(pSdoComCon_p-> |
| m_SdoSeqConHdl, |
| uiSizeOfFrame, |
| pFrame); |
| |
| } else |
| if ((pSdoComCon_p->m_uiTransferredByte > 0) |
| && (pSdoComCon_p->m_uiTransSize > EPL_SDO_MAX_PAYLOAD)) { // segment |
| // set segment flag |
| bFlag = |
| AmiGetByteFromLe(&pCommandFrame-> |
| m_le_bFlags); |
| bFlag |= 0x20; |
| AmiSetByteToLe(&pCommandFrame-> |
| m_le_bFlags, bFlag); |
| |
| // copy data in frame |
| EPL_MEMCPY(&pCommandFrame-> |
| m_le_abCommandData[0], |
| pSdoComCon_p->m_pData, |
| EPL_SDO_MAX_PAYLOAD); |
| |
| // correct byte-counter |
| pSdoComCon_p->m_uiTransSize -= |
| EPL_SDO_MAX_PAYLOAD; |
| pSdoComCon_p->m_uiTransferredByte += |
| EPL_SDO_MAX_PAYLOAD; |
| // move data pointer |
| pSdoComCon_p->m_pData += |
| EPL_SDO_MAX_PAYLOAD; |
| |
| // set segment size |
| AmiSetWordToLe(&pCommandFrame-> |
| m_le_wSegmentSize, |
| EPL_SDO_MAX_PAYLOAD); |
| |
| // send frame |
| uiSizeOfFrame += EPL_SDO_MAX_PAYLOAD; |
| Ret = |
| EplSdoAsySeqSendData(pSdoComCon_p-> |
| m_SdoSeqConHdl, |
| uiSizeOfFrame, |
| pFrame); |
| } else { |
| if ((pSdoComCon_p->m_uiTransSize == 0) |
| && (pSdoComCon_p-> |
| m_SdoServiceType != |
| kEplSdoServiceWriteByIndex)) { |
| goto Exit; |
| } |
| // complete |
| // set segment complete flag |
| bFlag = |
| AmiGetByteFromLe(&pCommandFrame-> |
| m_le_bFlags); |
| bFlag |= 0x30; |
| AmiSetByteToLe(&pCommandFrame-> |
| m_le_bFlags, bFlag); |
| |
| // copy data in frame |
| EPL_MEMCPY(&pCommandFrame-> |
| m_le_abCommandData[0], |
| pSdoComCon_p->m_pData, |
| pSdoComCon_p->m_uiTransSize); |
| |
| // correct byte-counter |
| pSdoComCon_p->m_uiTransferredByte += |
| pSdoComCon_p->m_uiTransSize; |
| |
| // move data pointer |
| pSdoComCon_p->m_pData += |
| pSdoComCon_p->m_uiTransSize; |
| |
| // set segment size |
| AmiSetWordToLe(&pCommandFrame-> |
| m_le_wSegmentSize, |
| (u16) pSdoComCon_p-> |
| m_uiTransSize); |
| |
| // send frame |
| uiSizeOfFrame += |
| pSdoComCon_p->m_uiTransSize; |
| pSdoComCon_p->m_uiTransSize = 0; |
| Ret = |
| EplSdoAsySeqSendData(pSdoComCon_p-> |
| m_SdoSeqConHdl, |
| uiSizeOfFrame, |
| pFrame); |
| } |
| |
| } |
| break; |
| } |
| // abort to send |
| case kEplSdoComSendTypeAbort: |
| { |
| // set response and abort flag |
| bFlag = AmiGetByteFromLe(&pCommandFrame->m_le_bFlags); |
| bFlag |= 0xC0; |
| AmiSetByteToLe(&pCommandFrame->m_le_bFlags, bFlag); |
| |
| // copy abortcode to frame |
| AmiSetDwordToLe(&pCommandFrame->m_le_abCommandData[0], |
| *((u32 *) pSdoComCon_p->m_pData)); |
| |
| // set size of segment |
| AmiSetWordToLe(&pCommandFrame->m_le_wSegmentSize, |
| sizeof(u32)); |
| |
| // update counter |
| pSdoComCon_p->m_uiTransferredByte = sizeof(u32); |
| pSdoComCon_p->m_uiTransSize = 0; |
| |
| // calc framesize |
| uiSizeOfFrame += sizeof(u32); |
| Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl, |
| uiSizeOfFrame, pFrame); |
| break; |
| } |
| } // end of switch(SendType_p) |
| |
| Exit: |
| return Ret; |
| } |
| #endif |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplSdoComServerInitWriteByIndex |
| // |
| // Description: function start the processing of an write by index command |
| // |
| // |
| // |
| // Parameters: pSdoComCon_p = pointer to control structure of connection |
| // pAsySdoCom_p = pointer to received frame |
| // |
| // Returns: tEplKernel = errorcode |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) |
| static tEplKernel EplSdoComServerInitWriteByIndex(tEplSdoComCon * pSdoComCon_p, |
| tEplAsySdoCom * pAsySdoCom_p) |
| { |
| tEplKernel Ret = kEplSuccessful; |
| unsigned int uiIndex; |
| unsigned int uiSubindex; |
| unsigned int uiBytesToTransfer; |
| tEplObdSize EntrySize; |
| tEplObdAccess AccessType; |
| u32 dwAbortCode; |
| u8 *pbSrcData; |
| |
| dwAbortCode = 0; |
| |
| // a init of a write |
| // -> variable part of header possible |
| |
| // check if expedited or segmented transfer |
| if ((pAsySdoCom_p->m_le_bFlags & 0x30) == 0x10) { // initiate segmented transfer |
| pSdoComCon_p->m_SdoTransType = kEplSdoTransSegmented; |
| // get index and subindex |
| uiIndex = |
| AmiGetWordFromLe(&pAsySdoCom_p->m_le_abCommandData[4]); |
| uiSubindex = |
| AmiGetByteFromLe(&pAsySdoCom_p->m_le_abCommandData[6]); |
| // get source-pointer for copy |
| pbSrcData = &pAsySdoCom_p->m_le_abCommandData[8]; |
| // save size |
| pSdoComCon_p->m_uiTransSize = |
| AmiGetDwordFromLe(&pAsySdoCom_p->m_le_abCommandData[0]); |
| |
| } else if ((pAsySdoCom_p->m_le_bFlags & 0x30) == 0x00) { // expedited transfer |
| pSdoComCon_p->m_SdoTransType = kEplSdoTransExpedited; |
| // get index and subindex |
| uiIndex = |
| AmiGetWordFromLe(&pAsySdoCom_p->m_le_abCommandData[0]); |
| uiSubindex = |
| AmiGetByteFromLe(&pAsySdoCom_p->m_le_abCommandData[2]); |
| // get source-pointer for copy |
| pbSrcData = &pAsySdoCom_p->m_le_abCommandData[4]; |
| // save size |
| pSdoComCon_p->m_uiTransSize = |
| AmiGetWordFromLe(&pAsySdoCom_p->m_le_wSegmentSize); |
| // subtract header |
| pSdoComCon_p->m_uiTransSize -= 4; |
| |
| } else { |
| // just ignore any other transfer type |
| goto Exit; |
| } |
| |
| // check accesstype of entry |
| // existens of entry |
| //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) |
| Ret = EplObduGetAccessType(uiIndex, uiSubindex, &AccessType); |
| /*#else |
| Ret = kEplObdSubindexNotExist; |
| AccessType = 0; |
| #endif*/ |
| if (Ret == kEplObdSubindexNotExist) { // subentry doesn't exist |
| pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_SUB_INDEX_NOT_EXIST; |
| // send abort |
| // d.k. This is wrong: k.t. not needed send abort on end of write |
| /*pSdoComCon_p->m_pData = (u8*)pSdoComCon_p->m_dwLastAbortCode; |
| Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, |
| uiIndex, |
| uiSubindex, |
| kEplSdoComSendTypeAbort); */ |
| goto Abort; |
| } else if (Ret != kEplSuccessful) { // entry doesn't exist |
| pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_OBJECT_NOT_EXIST; |
| // send abort |
| // d.k. This is wrong: k.t. not needed send abort on end of write |
| /* |
| pSdoComCon_p->m_pData = (u8*)&dwAbortCode; |
| Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, |
| uiIndex, |
| uiSubindex, |
| kEplSdoComSendTypeAbort); */ |
| goto Abort; |
| } |
| // compare accesstype must be read |
| if ((AccessType & kEplObdAccWrite) == 0) { |
| |
| if ((AccessType & kEplObdAccRead) != 0) { |
| // entry write a read only object |
| pSdoComCon_p->m_dwLastAbortCode = |
| EPL_SDOAC_WRITE_TO_READ_ONLY_OBJ; |
| } else { |
| pSdoComCon_p->m_dwLastAbortCode = |
| EPL_SDOAC_UNSUPPORTED_ACCESS; |
| } |
| // send abort |
| // d.k. This is wrong: k.t. not needed send abort on end of write |
| /*pSdoComCon_p->m_pData = (u8*)&dwAbortCode; |
| Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, |
| uiIndex, |
| uiSubindex, |
| kEplSdoComSendTypeAbort); */ |
| goto Abort; |
| } |
| // save service |
| pSdoComCon_p->m_SdoServiceType = kEplSdoServiceWriteByIndex; |
| |
| pSdoComCon_p->m_uiTransferredByte = 0; |
| |
| // write data to OD |
| if (pSdoComCon_p->m_SdoTransType == kEplSdoTransExpedited) { // expedited transfer |
| // size checking is done by EplObduWriteEntryFromLe() |
| |
| //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) |
| Ret = EplObduWriteEntryFromLe(uiIndex, |
| uiSubindex, |
| pbSrcData, |
| pSdoComCon_p->m_uiTransSize); |
| switch (Ret) { |
| case kEplSuccessful: |
| { |
| break; |
| } |
| |
| case kEplObdAccessViolation: |
| { |
| pSdoComCon_p->m_dwLastAbortCode = |
| EPL_SDOAC_UNSUPPORTED_ACCESS; |
| // send abort |
| goto Abort; |
| } |
| |
| case kEplObdValueLengthError: |
| { |
| pSdoComCon_p->m_dwLastAbortCode = |
| EPL_SDOAC_DATA_TYPE_LENGTH_NOT_MATCH; |
| // send abort |
| goto Abort; |
| } |
| |
| case kEplObdValueTooHigh: |
| { |
| pSdoComCon_p->m_dwLastAbortCode = |
| EPL_SDOAC_VALUE_RANGE_TOO_HIGH; |
| // send abort |
| goto Abort; |
| } |
| |
| case kEplObdValueTooLow: |
| { |
| pSdoComCon_p->m_dwLastAbortCode = |
| EPL_SDOAC_VALUE_RANGE_TOO_LOW; |
| // send abort |
| goto Abort; |
| } |
| |
| default: |
| { |
| pSdoComCon_p->m_dwLastAbortCode = |
| EPL_SDOAC_GENERAL_ERROR; |
| // send abort |
| goto Abort; |
| } |
| } |
| //#endif |
| // send command acknowledge |
| Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, |
| 0, |
| 0, |
| kEplSdoComSendTypeAckRes); |
| |
| pSdoComCon_p->m_uiTransSize = 0; |
| goto Exit; |
| } else { |
| // get size of the object to check if it fits |
| // because we directly write to the destination memory |
| // d.k. no one calls the user OD callback function |
| |
| //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) |
| EntrySize = EplObduGetDataSize(uiIndex, uiSubindex); |
| /*#else |
| EntrySize = 0; |
| #endif */ |
| if (EntrySize < pSdoComCon_p->m_uiTransSize) { // parameter too big |
| pSdoComCon_p->m_dwLastAbortCode = |
| EPL_SDOAC_DATA_TYPE_LENGTH_TOO_HIGH; |
| // send abort |
| // d.k. This is wrong: k.t. not needed send abort on end of write |
| /*pSdoComCon_p->m_pData = (u8*)&dwAbortCode; |
| Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, |
| uiIndex, |
| uiSubindex, |
| kEplSdoComSendTypeAbort); */ |
| goto Abort; |
| } |
| |
| uiBytesToTransfer = |
| AmiGetWordFromLe(&pAsySdoCom_p->m_le_wSegmentSize); |
| // eleminate header (Command header (8) + variable part (4) + Command header (4)) |
| uiBytesToTransfer -= 16; |
| // get pointer to object entry |
| //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) |
| pSdoComCon_p->m_pData = EplObduGetObjectDataPtr(uiIndex, |
| uiSubindex); |
| //#endif |
| if (pSdoComCon_p->m_pData == NULL) { |
| pSdoComCon_p->m_dwLastAbortCode = |
| EPL_SDOAC_GENERAL_ERROR; |
| // send abort |
| // d.k. This is wrong: k.t. not needed send abort on end of write |
| /* pSdoComCon_p->m_pData = (u8*)&pSdoComCon_p->m_dwLastAbortCode; |
| Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p, |
| uiIndex, |
| uiSubindex, |
| kEplSdoComSendTypeAbort);*/ |
| goto Abort; |
| } |
| // copy data |
| EPL_MEMCPY(pSdoComCon_p->m_pData, pbSrcData, uiBytesToTransfer); |
| |
| // update internal counter |
| pSdoComCon_p->m_uiTransferredByte = uiBytesToTransfer; |
| pSdoComCon_p->m_uiTransSize -= uiBytesToTransfer; |
| |
| // update target pointer |
| ( /*(u8*) */ pSdoComCon_p->m_pData) += uiBytesToTransfer; |
| |
| // send acknowledge without any Command layer data |
| Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl, |
| 0, (tEplFrame *) NULL); |
| goto Exit; |
| } |
| |
| Abort: |
| if (pSdoComCon_p->m_dwLastAbortCode != 0) { |
| // send abort |
| pSdoComCon_p->m_pData = |
| (u8 *) & pSdoComCon_p->m_dwLastAbortCode; |
| Ret = |
| EplSdoComServerSendFrameIntern(pSdoComCon_p, uiIndex, |
| uiSubindex, |
| kEplSdoComSendTypeAbort); |
| |
| // reset abort code |
| pSdoComCon_p->m_dwLastAbortCode = 0; |
| pSdoComCon_p->m_uiTransSize = 0; |
| goto Exit; |
| } |
| |
| Exit: |
| return Ret; |
| } |
| #endif |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplSdoComClientSend |
| // |
| // Description: function starts an sdo transfer an send all further frames |
| // |
| // |
| // |
| // Parameters: pSdoComCon_p = pointer to control structure of connection |
| // |
| // Returns: tEplKernel = errorcode |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) |
| static tEplKernel EplSdoComClientSend(tEplSdoComCon * pSdoComCon_p) |
| { |
| tEplKernel Ret; |
| u8 abFrame[EPL_MAX_SDO_FRAME_SIZE]; |
| tEplFrame *pFrame; |
| tEplAsySdoCom *pCommandFrame; |
| unsigned int uiSizeOfFrame; |
| u8 bFlags; |
| u8 *pbPayload; |
| |
| Ret = kEplSuccessful; |
| |
| pFrame = (tEplFrame *) & abFrame[0]; |
| |
| EPL_MEMSET(&abFrame[0], 0x00, sizeof(abFrame)); |
| |
| // build generic part of frame |
| // get pointer to command layerpart of frame |
| pCommandFrame = |
| &pFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame. |
| m_le_abSdoSeqPayload; |
| AmiSetByteToLe(&pCommandFrame->m_le_bCommandId, |
| pSdoComCon_p->m_SdoServiceType); |
| AmiSetByteToLe(&pCommandFrame->m_le_bTransactionId, |
| pSdoComCon_p->m_bTransactionId); |
| |
| // set size constant part of header |
| uiSizeOfFrame = 8; |
| |
| // check if first frame to send -> command header needed |
| if (pSdoComCon_p->m_uiTransSize > 0) { |
| if (pSdoComCon_p->m_uiTransferredByte == 0) { // start SDO transfer |
| // check if segmented or expedited transfer |
| // only for write commands |
| switch (pSdoComCon_p->m_SdoServiceType) { |
| case kEplSdoServiceReadByIndex: |
| { // first frame of read access always expedited |
| pSdoComCon_p->m_SdoTransType = |
| kEplSdoTransExpedited; |
| pbPayload = |
| &pCommandFrame-> |
| m_le_abCommandData[0]; |
| // fill rest of header |
| AmiSetWordToLe(&pCommandFrame-> |
| m_le_wSegmentSize, 4); |
| |
| // create command header |
| AmiSetWordToLe(pbPayload, |
| (u16) pSdoComCon_p-> |
| m_uiTargetIndex); |
| pbPayload += 2; |
| AmiSetByteToLe(pbPayload, |
| (u8) pSdoComCon_p-> |
| m_uiTargetSubIndex); |
| // calc size |
| uiSizeOfFrame += 4; |
| |
| // set pSdoComCon_p->m_uiTransferredByte to one |
| pSdoComCon_p->m_uiTransferredByte = 1; |
| break; |
| } |
| |
| case kEplSdoServiceWriteByIndex: |
| { |
| if (pSdoComCon_p->m_uiTransSize > EPL_SDO_MAX_PAYLOAD) { // segmented transfer |
| // -> variable part of header needed |
| // save that transfer is segmented |
| pSdoComCon_p->m_SdoTransType = |
| kEplSdoTransSegmented; |
| // fill variable part of header |
| AmiSetDwordToLe(&pCommandFrame-> |
| m_le_abCommandData |
| [0], |
| pSdoComCon_p-> |
| m_uiTransSize); |
| // set pointer to real payload |
| pbPayload = |
| &pCommandFrame-> |
| m_le_abCommandData[4]; |
| // fill rest of header |
| AmiSetWordToLe(&pCommandFrame-> |
| m_le_wSegmentSize, |
| EPL_SDO_MAX_PAYLOAD); |
| bFlags = 0x10; |
| AmiSetByteToLe(&pCommandFrame-> |
| m_le_bFlags, |
| bFlags); |
| // create command header |
| AmiSetWordToLe(pbPayload, |
| (u16) |
| pSdoComCon_p-> |
| m_uiTargetIndex); |
| pbPayload += 2; |
| AmiSetByteToLe(pbPayload, |
| (u8) |
| pSdoComCon_p-> |
| m_uiTargetSubIndex); |
| // on byte for reserved |
| pbPayload += 2; |
| // calc size |
| uiSizeOfFrame += |
| EPL_SDO_MAX_PAYLOAD; |
| |
| // copy payload |
| EPL_MEMCPY(pbPayload, |
| pSdoComCon_p-> |
| m_pData, |
| (EPL_SDO_MAX_PAYLOAD |
| - 8)); |
| pSdoComCon_p->m_pData += |
| (EPL_SDO_MAX_PAYLOAD - 8); |
| // correct intern counter |
| pSdoComCon_p->m_uiTransSize -= |
| (EPL_SDO_MAX_PAYLOAD - 8); |
| pSdoComCon_p-> |
| m_uiTransferredByte = |
| (EPL_SDO_MAX_PAYLOAD - 8); |
| |
| } else { // expedited trandsfer |
| // save that transfer is expedited |
| pSdoComCon_p->m_SdoTransType = |
| kEplSdoTransExpedited; |
| pbPayload = |
| &pCommandFrame-> |
| m_le_abCommandData[0]; |
| |
| // create command header |
| AmiSetWordToLe(pbPayload, |
| (u16) |
| pSdoComCon_p-> |
| m_uiTargetIndex); |
| pbPayload += 2; |
| AmiSetByteToLe(pbPayload, |
| (u8) |
| pSdoComCon_p-> |
| m_uiTargetSubIndex); |
| // + 2 -> one byte for subindex and one byte reserved |
| pbPayload += 2; |
| // copy data |
| EPL_MEMCPY(pbPayload, |
| pSdoComCon_p-> |
| m_pData, |
| pSdoComCon_p-> |
| m_uiTransSize); |
| // calc size |
| uiSizeOfFrame += |
| (4 + |
| pSdoComCon_p-> |
| m_uiTransSize); |
| // fill rest of header |
| AmiSetWordToLe(&pCommandFrame-> |
| m_le_wSegmentSize, |
| (u16) (4 + |
| pSdoComCon_p-> |
| m_uiTransSize)); |
| |
| pSdoComCon_p-> |
| m_uiTransferredByte = |
| pSdoComCon_p->m_uiTransSize; |
| pSdoComCon_p->m_uiTransSize = 0; |
| } |
| break; |
| } |
| |
| case kEplSdoServiceNIL: |
| default: |
| // invalid service requested |
| Ret = kEplSdoComInvalidServiceType; |
| goto Exit; |
| } // end of switch(pSdoComCon_p->m_SdoServiceType) |
| } else // (pSdoComCon_p->m_uiTransferredByte > 0) |
| { // continue SDO transfer |
| switch (pSdoComCon_p->m_SdoServiceType) { |
| // for expedited read is nothing to do |
| // -> server sends data |
| |
| case kEplSdoServiceWriteByIndex: |
| { // send next frame |
| if (pSdoComCon_p->m_SdoTransType == |
| kEplSdoTransSegmented) { |
| if (pSdoComCon_p->m_uiTransSize > EPL_SDO_MAX_PAYLOAD) { // next segment |
| pbPayload = |
| &pCommandFrame-> |
| m_le_abCommandData |
| [0]; |
| // fill rest of header |
| AmiSetWordToLe |
| (&pCommandFrame-> |
| m_le_wSegmentSize, |
| EPL_SDO_MAX_PAYLOAD); |
| bFlags = 0x20; |
| AmiSetByteToLe |
| (&pCommandFrame-> |
| m_le_bFlags, |
| bFlags); |
| // copy data |
| EPL_MEMCPY(pbPayload, |
| pSdoComCon_p-> |
| m_pData, |
| EPL_SDO_MAX_PAYLOAD); |
| pSdoComCon_p->m_pData += |
| EPL_SDO_MAX_PAYLOAD; |
| // correct intern counter |
| pSdoComCon_p-> |
| m_uiTransSize -= |
| EPL_SDO_MAX_PAYLOAD; |
| pSdoComCon_p-> |
| m_uiTransferredByte |
| = |
| EPL_SDO_MAX_PAYLOAD; |
| // calc size |
| uiSizeOfFrame += |
| EPL_SDO_MAX_PAYLOAD; |
| |
| } else { // end of transfer |
| pbPayload = |
| &pCommandFrame-> |
| m_le_abCommandData |
| [0]; |
| // fill rest of header |
| AmiSetWordToLe |
| (&pCommandFrame-> |
| m_le_wSegmentSize, |
| (u16) |
| pSdoComCon_p-> |
| m_uiTransSize); |
| bFlags = 0x30; |
| AmiSetByteToLe |
| (&pCommandFrame-> |
| m_le_bFlags, |
| bFlags); |
| // copy data |
| EPL_MEMCPY(pbPayload, |
| pSdoComCon_p-> |
| m_pData, |
| pSdoComCon_p-> |
| m_uiTransSize); |
| pSdoComCon_p->m_pData += |
| pSdoComCon_p-> |
| m_uiTransSize; |
| // calc size |
| uiSizeOfFrame += |
| pSdoComCon_p-> |
| m_uiTransSize; |
| // correct intern counter |
| pSdoComCon_p-> |
| m_uiTransSize = 0; |
| pSdoComCon_p-> |
| m_uiTransferredByte |
| = |
| pSdoComCon_p-> |
| m_uiTransSize; |
| |
| } |
| } else { |
| goto Exit; |
| } |
| break; |
| } |
| default: |
| { |
| goto Exit; |
| } |
| } // end of switch(pSdoComCon_p->m_SdoServiceType) |
| } |
| } else { |
| goto Exit; |
| } |
| |
| // call send function of lower layer |
| switch (pSdoComCon_p->m_SdoProtType) { |
| case kEplSdoTypeAsnd: |
| case kEplSdoTypeUdp: |
| { |
| Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl, |
| uiSizeOfFrame, pFrame); |
| break; |
| } |
| |
| default: |
| { |
| Ret = kEplSdoComUnsupportedProt; |
| } |
| } // end of switch(pSdoComCon_p->m_SdoProtType) |
| |
| Exit: |
| return Ret; |
| |
| } |
| #endif |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplSdoComClientProcessFrame |
| // |
| // Description: function process a received frame |
| // |
| // |
| // |
| // Parameters: SdoComCon_p = connection handle |
| // pAsySdoCom_p = pointer to frame to process |
| // |
| // Returns: tEplKernel = errorcode |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) |
| static tEplKernel EplSdoComClientProcessFrame(tEplSdoComConHdl SdoComCon_p, |
| tEplAsySdoCom * pAsySdoCom_p) |
| { |
| tEplKernel Ret; |
| u8 bBuffer; |
| unsigned int uiBuffer; |
| unsigned int uiDataSize; |
| unsigned long ulBuffer; |
| tEplSdoComCon *pSdoComCon; |
| |
| Ret = kEplSuccessful; |
| |
| // get pointer to control structure |
| pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComCon_p]; |
| |
| // check if transaction Id fit |
| bBuffer = AmiGetByteFromLe(&pAsySdoCom_p->m_le_bTransactionId); |
| if (pSdoComCon->m_bTransactionId != bBuffer) { |
| // incorrect transaction id |
| |
| // if running transfer |
| if ((pSdoComCon->m_uiTransferredByte != 0) |
| && (pSdoComCon->m_uiTransSize != 0)) { |
| pSdoComCon->m_dwLastAbortCode = EPL_SDOAC_GENERAL_ERROR; |
| // -> send abort |
| EplSdoComClientSendAbort(pSdoComCon, |
| pSdoComCon->m_dwLastAbortCode); |
| // call callback of application |
| Ret = |
| EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, |
| kEplSdoComTransferTxAborted); |
| } |
| |
| } else { // check if correct command |
| bBuffer = AmiGetByteFromLe(&pAsySdoCom_p->m_le_bCommandId); |
| if (pSdoComCon->m_SdoServiceType != bBuffer) { |
| // incorrect command |
| // if running transfer |
| if ((pSdoComCon->m_uiTransferredByte != 0) |
| && (pSdoComCon->m_uiTransSize != 0)) { |
| pSdoComCon->m_dwLastAbortCode = |
| EPL_SDOAC_GENERAL_ERROR; |
| // -> send abort |
| EplSdoComClientSendAbort(pSdoComCon, |
| pSdoComCon-> |
| m_dwLastAbortCode); |
| // call callback of application |
| Ret = |
| EplSdoComTransferFinished(SdoComCon_p, |
| pSdoComCon, |
| kEplSdoComTransferTxAborted); |
| } |
| |
| } else { // switch on command |
| switch (pSdoComCon->m_SdoServiceType) { |
| case kEplSdoServiceWriteByIndex: |
| { // check if confirmation from server |
| // nothing more to do |
| break; |
| } |
| |
| case kEplSdoServiceReadByIndex: |
| { // check if it is an segmented or an expedited transfer |
| bBuffer = |
| AmiGetByteFromLe(&pAsySdoCom_p-> |
| m_le_bFlags); |
| // mask uninteressting bits |
| bBuffer &= 0x30; |
| switch (bBuffer) { |
| // expedited transfer |
| case 0x00: |
| { |
| // check size of buffer |
| uiBuffer = |
| AmiGetWordFromLe |
| (&pAsySdoCom_p-> |
| m_le_wSegmentSize); |
| if (uiBuffer > pSdoComCon->m_uiTransSize) { // buffer provided by the application is to small |
| // copy only a part |
| uiDataSize = |
| pSdoComCon-> |
| m_uiTransSize; |
| } else { // buffer fits |
| uiDataSize = |
| uiBuffer; |
| } |
| |
| // copy data |
| EPL_MEMCPY(pSdoComCon-> |
| m_pData, |
| &pAsySdoCom_p-> |
| m_le_abCommandData |
| [0], |
| uiDataSize); |
| |
| // correct counter |
| pSdoComCon-> |
| m_uiTransSize = 0; |
| pSdoComCon-> |
| m_uiTransferredByte |
| = uiDataSize; |
| break; |
| } |
| |
| // start of a segmented transfer |
| case 0x10: |
| { // get total size of transfer |
| ulBuffer = |
| AmiGetDwordFromLe |
| (&pAsySdoCom_p-> |
| m_le_abCommandData |
| [0]); |
| if (ulBuffer <= pSdoComCon->m_uiTransSize) { // buffer fit |
| pSdoComCon-> |
| m_uiTransSize |
| = |
| (unsigned |
| int) |
| ulBuffer; |
| } else { // buffer to small |
| // send abort |
| pSdoComCon-> |
| m_dwLastAbortCode |
| = |
| EPL_SDOAC_DATA_TYPE_LENGTH_TOO_HIGH; |
| // -> send abort |
| EplSdoComClientSendAbort |
| (pSdoComCon, |
| pSdoComCon-> |
| m_dwLastAbortCode); |
| // call callback of application |
| Ret = |
| EplSdoComTransferFinished |
| (SdoComCon_p, |
| pSdoComCon, |
| kEplSdoComTransferRxAborted); |
| goto Exit; |
| } |
| |
| // get segment size |
| // check size of buffer |
| uiBuffer = |
| AmiGetWordFromLe |
| (&pAsySdoCom_p-> |
| m_le_wSegmentSize); |
| // subtract size of vaiable header from datasize |
| uiBuffer -= 4; |
| // copy data |
| EPL_MEMCPY(pSdoComCon-> |
| m_pData, |
| &pAsySdoCom_p-> |
| m_le_abCommandData |
| [4], |
| uiBuffer); |
| |
| // correct counter an pointer |
| pSdoComCon->m_pData += |
| uiBuffer; |
| pSdoComCon-> |
| m_uiTransferredByte |
| += uiBuffer; |
| pSdoComCon-> |
| m_uiTransSize -= |
| uiBuffer; |
| |
| break; |
| } |
| |
| // segment |
| case 0x20: |
| { |
| // get segment size |
| // check size of buffer |
| uiBuffer = |
| AmiGetWordFromLe |
| (&pAsySdoCom_p-> |
| m_le_wSegmentSize); |
| // check if data to copy fit to buffer |
| if (uiBuffer >= pSdoComCon->m_uiTransSize) { // to much data |
| uiBuffer = |
| (pSdoComCon-> |
| m_uiTransSize |
| - 1); |
| } |
| // copy data |
| EPL_MEMCPY(pSdoComCon-> |
| m_pData, |
| &pAsySdoCom_p-> |
| m_le_abCommandData |
| [0], |
| uiBuffer); |
| |
| // correct counter an pointer |
| pSdoComCon->m_pData += |
| uiBuffer; |
| pSdoComCon-> |
| m_uiTransferredByte |
| += uiBuffer; |
| pSdoComCon-> |
| m_uiTransSize -= |
| uiBuffer; |
| break; |
| } |
| |
| // last segment |
| case 0x30: |
| { |
| // get segment size |
| // check size of buffer |
| uiBuffer = |
| AmiGetWordFromLe |
| (&pAsySdoCom_p-> |
| m_le_wSegmentSize); |
| // check if data to copy fit to buffer |
| if (uiBuffer > pSdoComCon->m_uiTransSize) { // to much data |
| uiBuffer = |
| (pSdoComCon-> |
| m_uiTransSize |
| - 1); |
| } |
| // copy data |
| EPL_MEMCPY(pSdoComCon-> |
| m_pData, |
| &pAsySdoCom_p-> |
| m_le_abCommandData |
| [0], |
| uiBuffer); |
| |
| // correct counter an pointer |
| pSdoComCon->m_pData += |
| uiBuffer; |
| pSdoComCon-> |
| m_uiTransferredByte |
| += uiBuffer; |
| pSdoComCon-> |
| m_uiTransSize = 0; |
| |
| break; |
| } |
| } // end of switch(bBuffer & 0x30) |
| |
| break; |
| } |
| |
| case kEplSdoServiceNIL: |
| default: |
| // invalid service requested |
| // $$$ d.k. What should we do? |
| break; |
| } // end of switch(pSdoComCon->m_SdoServiceType) |
| } |
| } |
| |
| Exit: |
| return Ret; |
| } |
| #endif |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplSdoComClientSendAbort |
| // |
| // Description: function send a abort message |
| // |
| // |
| // |
| // Parameters: pSdoComCon_p = pointer to control structure of connection |
| // dwAbortCode_p = Sdo abort code |
| // |
| // Returns: tEplKernel = errorcode |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) |
| static tEplKernel EplSdoComClientSendAbort(tEplSdoComCon * pSdoComCon_p, |
| u32 dwAbortCode_p) |
| { |
| tEplKernel Ret; |
| u8 abFrame[EPL_MAX_SDO_FRAME_SIZE]; |
| tEplFrame *pFrame; |
| tEplAsySdoCom *pCommandFrame; |
| unsigned int uiSizeOfFrame; |
| |
| Ret = kEplSuccessful; |
| |
| pFrame = (tEplFrame *) & abFrame[0]; |
| |
| EPL_MEMSET(&abFrame[0], 0x00, sizeof(abFrame)); |
| |
| // build generic part of frame |
| // get pointer to command layerpart of frame |
| pCommandFrame = |
| &pFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame. |
| m_le_abSdoSeqPayload; |
| AmiSetByteToLe(&pCommandFrame->m_le_bCommandId, |
| pSdoComCon_p->m_SdoServiceType); |
| AmiSetByteToLe(&pCommandFrame->m_le_bTransactionId, |
| pSdoComCon_p->m_bTransactionId); |
| |
| uiSizeOfFrame = 8; |
| |
| // set response and abort flag |
| pCommandFrame->m_le_bFlags |= 0x40; |
| |
| // copy abortcode to frame |
| AmiSetDwordToLe(&pCommandFrame->m_le_abCommandData[0], dwAbortCode_p); |
| |
| // set size of segment |
| AmiSetWordToLe(&pCommandFrame->m_le_wSegmentSize, sizeof(u32)); |
| |
| // update counter |
| pSdoComCon_p->m_uiTransferredByte = sizeof(u32); |
| pSdoComCon_p->m_uiTransSize = 0; |
| |
| // calc framesize |
| uiSizeOfFrame += sizeof(u32); |
| |
| // save abort code |
| pSdoComCon_p->m_dwLastAbortCode = dwAbortCode_p; |
| |
| // call send function of lower layer |
| switch (pSdoComCon_p->m_SdoProtType) { |
| case kEplSdoTypeAsnd: |
| case kEplSdoTypeUdp: |
| { |
| Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl, |
| uiSizeOfFrame, pFrame); |
| break; |
| } |
| |
| default: |
| { |
| Ret = kEplSdoComUnsupportedProt; |
| } |
| } // end of switch(pSdoComCon_p->m_SdoProtType) |
| |
| return Ret; |
| } |
| #endif |
| |
| //--------------------------------------------------------------------------- |
| // |
| // Function: EplSdoComTransferFinished |
| // |
| // Description: calls callback function of application if available |
| // and clears entry in control structure |
| // |
| // Parameters: pSdoComCon_p = pointer to control structure of connection |
| // SdoComConState_p = state of SDO transfer |
| // |
| // Returns: tEplKernel = errorcode |
| // |
| // |
| // State: |
| // |
| //--------------------------------------------------------------------------- |
| static tEplKernel EplSdoComTransferFinished(tEplSdoComConHdl SdoComCon_p, |
| tEplSdoComCon * pSdoComCon_p, |
| tEplSdoComConState SdoComConState_p) |
| { |
| tEplKernel Ret; |
| |
| Ret = kEplSuccessful; |
| |
| if (pSdoComCon_p->m_pfnTransferFinished != NULL) { |
| tEplSdoFinishedCb pfnTransferFinished; |
| tEplSdoComFinished SdoComFinished; |
| |
| SdoComFinished.m_pUserArg = pSdoComCon_p->m_pUserArg; |
| SdoComFinished.m_uiNodeId = pSdoComCon_p->m_uiNodeId; |
| SdoComFinished.m_uiTargetIndex = pSdoComCon_p->m_uiTargetIndex; |
| SdoComFinished.m_uiTargetSubIndex = |
| pSdoComCon_p->m_uiTargetSubIndex; |
| SdoComFinished.m_uiTransferredByte = |
| pSdoComCon_p->m_uiTransferredByte; |
| SdoComFinished.m_dwAbortCode = pSdoComCon_p->m_dwLastAbortCode; |
| SdoComFinished.m_SdoComConHdl = SdoComCon_p; |
| SdoComFinished.m_SdoComConState = SdoComConState_p; |
| if (pSdoComCon_p->m_SdoServiceType == |
| kEplSdoServiceWriteByIndex) { |
| SdoComFinished.m_SdoAccessType = kEplSdoAccessTypeWrite; |
| } else { |
| SdoComFinished.m_SdoAccessType = kEplSdoAccessTypeRead; |
| } |
| |
| // reset transfer state so this handle is not busy anymore |
| pSdoComCon_p->m_uiTransferredByte = 0; |
| pSdoComCon_p->m_uiTransSize = 0; |
| |
| pfnTransferFinished = pSdoComCon_p->m_pfnTransferFinished; |
| // delete function pointer to inform application only once for each transfer |
| pSdoComCon_p->m_pfnTransferFinished = NULL; |
| |
| // call application's callback function |
| pfnTransferFinished(&SdoComFinished); |
| |
| } |
| |
| return Ret; |
| } |
| |
| // EOF |