aboutsummaryrefslogtreecommitdiff
path: root/drivers/staging/epl/EplSdoComu.c
diff options
context:
space:
mode:
authorDaniel Krueger <daniel.krueger@systec-electronic.com>2008-12-19 11:41:57 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2009-01-06 13:52:36 -0800
commit9d7164cfdb611c2f864d535ae5794f23db3d84f7 (patch)
tree046847f7d6432f1f3dc8236f62492503f4c9ebdc /drivers/staging/epl/EplSdoComu.c
parent37bcd24b845abbfd85c838ee9ce07c2b254d3a05 (diff)
Staging: add epl stack
This is the openPOWERLINK network stack from systec electronic. It's a bit messed up as there is a driver mixed into the middle of it, lots of work needs to be done to unwind the different portions to make it sane. Cc: Daniel Krueger <daniel.krueger@systec-electronic.com> Cc: Ronald Sieber <Ronald.Sieber@systec-electronic.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/epl/EplSdoComu.c')
-rw-r--r--drivers/staging/epl/EplSdoComu.c3029
1 files changed, 3029 insertions, 0 deletions
diff --git a/drivers/staging/epl/EplSdoComu.c b/drivers/staging/epl/EplSdoComu.c
new file mode 100644
index 00000000000..ce5af66bfed
--- /dev/null
+++ b/drivers/staging/epl/EplSdoComu.c
@@ -0,0 +1,3029 @@
+/****************************************************************************
+
+ (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
+