diff options
Diffstat (limited to 'drivers/staging/epl/EplSdoComu.c')
-rw-r--r-- | drivers/staging/epl/EplSdoComu.c | 3346 |
1 files changed, 3346 insertions, 0 deletions
diff --git a/drivers/staging/epl/EplSdoComu.c b/drivers/staging/epl/EplSdoComu.c new file mode 100644 index 000000000000..ce0eb33f4c41 --- /dev/null +++ b/drivers/staging/epl/EplSdoComu.c @@ -0,0 +1,3346 @@ +/**************************************************************************** + + (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; + BYTE 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 + BYTE *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 + + DWORD 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 PUBLIC EplSdoComReceiveCb(tEplSdoSeqConHdl SdoSeqConHdl_p, + tEplAsySdoCom * pAsySdoCom_p, + unsigned int uiDataSize_p); + +tEplKernel PUBLIC 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, + DWORD 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 PUBLIC EplSdoComInit(void) +{ + tEplKernel Ret; + + Ret = EplSdoComAddInstance(); + + return Ret; + +} + +//--------------------------------------------------------------------------- +// +// Function: EplSdoComAddInstance +// +// Description: Init additional instance of the module +// +// +// +// Parameters: +// +// +// Returns: tEplKernel = errorcode +// +// +// State: +// +//--------------------------------------------------------------------------- +tEplKernel PUBLIC 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 PUBLIC 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 PUBLIC 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 PUBLIC 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 PUBLIC 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 PUBLIC 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 PUBLIC EplSdoComSdoAbort(tEplSdoComConHdl SdoComConHdl_p, + DWORD 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 = (BYTE *) & 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 PUBLIC 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, (WORD) 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 PUBLIC 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; + BYTE bFlag; + +#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) + DWORD 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 + = + (BYTE + *) + & + 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) { + ( /*(BYTE*) */ + 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 + = + (BYTE + *) + & + 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, + *((DWORD *) + pSdoComCon-> + m_pData)); + + // inc transaction id + pSdoComCon->m_bTransactionId++; + // call callback of application + pSdoComCon->m_dwLastAbortCode = + *((DWORD *) 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, + *((DWORD *) + pSdoComCon-> + m_pData)); + + // inc transaction id + pSdoComCon->m_bTransactionId++; + // change state + pSdoComCon->m_SdoComState = + kEplSdoComStateClientConnected; + // call callback of application + pSdoComCon->m_dwLastAbortCode = + *((DWORD *) 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; + DWORD 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 = (BYTE *) & 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 = (BYTE *) & 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 = (BYTE *) & 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 = (BYTE *) & 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; + BYTE abFrame[EPL_MAX_SDO_FRAME_SIZE]; + tEplFrame *pFrame; + tEplAsySdoCom *pCommandFrame; + unsigned int uiSizeOfFrame; + BYTE 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, + (WORD) 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, + (WORD) 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], + *((DWORD *) pSdoComCon_p->m_pData)); + + // set size of segment + AmiSetWordToLe(&pCommandFrame->m_le_wSegmentSize, + sizeof(DWORD)); + + // update counter + pSdoComCon_p->m_uiTransferredByte = sizeof(DWORD); + pSdoComCon_p->m_uiTransSize = 0; + + // calc framesize + uiSizeOfFrame += sizeof(DWORD); + 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; + DWORD dwAbortCode; + BYTE *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 = (BYTE*)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 = (BYTE*)&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 = (BYTE*)&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 = (BYTE*)&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 = (BYTE*)&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 + ( /*(BYTE*) */ 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 = + (BYTE *) & 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; + BYTE abFrame[EPL_MAX_SDO_FRAME_SIZE]; + tEplFrame *pFrame; + tEplAsySdoCom *pCommandFrame; + unsigned int uiSizeOfFrame; + BYTE bFlags; + BYTE *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, + (WORD) pSdoComCon_p-> + m_uiTargetIndex); + pbPayload += 2; + AmiSetByteToLe(pbPayload, + (BYTE) 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, + (WORD) + pSdoComCon_p-> + m_uiTargetIndex); + pbPayload += 2; + AmiSetByteToLe(pbPayload, + (BYTE) + 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, + (WORD) + pSdoComCon_p-> + m_uiTargetIndex); + pbPayload += 2; + AmiSetByteToLe(pbPayload, + (BYTE) + 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, + (WORD) (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, + (WORD) + 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; + BYTE 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, + DWORD dwAbortCode_p) +{ + tEplKernel Ret; + BYTE 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(DWORD)); + + // update counter + pSdoComCon_p->m_uiTransferredByte = sizeof(DWORD); + pSdoComCon_p->m_uiTransSize = 0; + + // calc framesize + uiSizeOfFrame += sizeof(DWORD); + + // 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 |