Staging: epl: remove PUBLIC definition
[linux-2.6/mini2440.git] / drivers / staging / epl / EplSdoComu.c
blobaf3d1b14674594fee16470feb207c53212ea18e7
1 /****************************************************************************
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
6 Project: openPOWERLINK
8 Description: source file for SDO Command Layer module
10 License:
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions
14 are met:
16 1. Redistributions of source code must retain the above copyright
17 notice, this list of conditions and the following disclaimer.
19 2. Redistributions in binary form must reproduce the above copyright
20 notice, this list of conditions and the following disclaimer in the
21 documentation and/or other materials provided with the distribution.
23 3. Neither the name of SYSTEC electronic GmbH nor the names of its
24 contributors may be used to endorse or promote products derived
25 from this software without prior written permission. For written
26 permission, please contact info@systec-electronic.com.
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32 COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
36 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
38 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 POSSIBILITY OF SUCH DAMAGE.
41 Severability Clause:
43 If a provision of this License is or becomes illegal, invalid or
44 unenforceable in any jurisdiction, that shall not affect:
45 1. the validity or enforceability in that jurisdiction of any other
46 provision of this License; or
47 2. the validity or enforceability in other jurisdictions of that or
48 any other provision of this License.
50 -------------------------------------------------------------------------
52 $RCSfile: EplSdoComu.c,v $
54 $Author: D.Krueger $
56 $Revision: 1.14 $ $Date: 2008/10/17 15:32:32 $
58 $State: Exp $
60 Build Environment:
61 GCC V3.4
63 -------------------------------------------------------------------------
65 Revision History:
67 2006/06/26 k.t.: start of the implementation
69 ****************************************************************************/
71 #include "user/EplSdoComu.h"
73 #if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) == 0) &&\
74 (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) == 0) )
76 #error 'ERROR: At least SDO Server or SDO Client should be activate!'
78 #endif
80 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
81 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) == 0) && (EPL_OBD_USE_KERNEL == FALSE)
83 #error 'ERROR: SDO Server needs OBDu module!'
85 #endif
87 #endif
89 /***************************************************************************/
90 /* */
91 /* */
92 /* G L O B A L D E F I N I T I O N S */
93 /* */
94 /* */
95 /***************************************************************************/
97 //---------------------------------------------------------------------------
98 // const defines
99 //---------------------------------------------------------------------------
101 #ifndef EPL_MAX_SDO_COM_CON
102 #define EPL_MAX_SDO_COM_CON 5
103 #endif
105 //---------------------------------------------------------------------------
106 // local types
107 //---------------------------------------------------------------------------
109 // intern events
110 typedef enum {
111 kEplSdoComConEventSendFirst = 0x00, // first frame to send
112 kEplSdoComConEventRec = 0x01, // frame received
113 kEplSdoComConEventConEstablished = 0x02, // connection established
114 kEplSdoComConEventConClosed = 0x03, // connection closed
115 kEplSdoComConEventAckReceived = 0x04, // acknowledge received by lower layer
116 // -> continue sending
117 kEplSdoComConEventFrameSended = 0x05, // lower has send a frame
118 kEplSdoComConEventInitError = 0x06, // error duringinitialisiation
119 // of the connection
120 kEplSdoComConEventTimeout = 0x07 // timeout in lower layer
121 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
124 kEplSdoComConEventInitCon = 0x08, // init connection (only client)
125 kEplSdoComConEventAbort = 0x09 // abort sdo transfer (only client)
126 #endif
127 } tEplSdoComConEvent;
129 typedef enum {
130 kEplSdoComSendTypeReq = 0x00, // send a request
131 kEplSdoComSendTypeAckRes = 0x01, // send a resonse without data
132 kEplSdoComSendTypeRes = 0x02, // send response with data
133 kEplSdoComSendTypeAbort = 0x03 // send abort
134 } tEplSdoComSendType;
136 // state of the state maschine
137 typedef enum {
138 // General State
139 kEplSdoComStateIdle = 0x00, // idle state
141 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
142 // Server States
143 kEplSdoComStateServerSegmTrans = 0x01, // send following frames
144 #endif
146 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
147 // Client States
148 kEplSdoComStateClientWaitInit = 0x10, // wait for init connection
149 // on lower layer
150 kEplSdoComStateClientConnected = 0x11, // connection established
151 kEplSdoComStateClientSegmTrans = 0x12 // send following frames
152 #endif
153 } tEplSdoComState;
155 // control structure for transaction
156 typedef struct {
157 tEplSdoSeqConHdl m_SdoSeqConHdl; // if != 0 -> entry used
158 tEplSdoComState m_SdoComState;
159 BYTE m_bTransactionId;
160 unsigned int m_uiNodeId; // NodeId of the target
161 // -> needed to reinit connection
162 // after timeout
163 tEplSdoTransType m_SdoTransType; // Auto, Expedited, Segmented
164 tEplSdoServiceType m_SdoServiceType; // WriteByIndex, ReadByIndex
165 tEplSdoType m_SdoProtType; // protocol layer: Auto, Udp, Asnd, Pdo
166 BYTE *m_pData; // pointer to data
167 unsigned int m_uiTransSize; // number of bytes
168 // to transfer
169 unsigned int m_uiTransferredByte; // number of bytes
170 // already transferred
171 tEplSdoFinishedCb m_pfnTransferFinished; // callback function of the
172 // application
173 // -> called in the end of
174 // the SDO transfer
175 void *m_pUserArg; // user definable argument pointer
177 DWORD m_dwLastAbortCode; // save the last abort code
178 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
179 // only for client
180 unsigned int m_uiTargetIndex; // index to access
181 unsigned int m_uiTargetSubIndex; // subiondex to access
183 // for future use
184 unsigned int m_uiTimeout; // timeout for this connection
186 #endif
188 } tEplSdoComCon;
190 // instance table
191 typedef struct {
192 tEplSdoComCon m_SdoComCon[EPL_MAX_SDO_COM_CON];
194 #if defined(WIN32) || defined(_WIN32)
195 LPCRITICAL_SECTION m_pCriticalSection;
196 CRITICAL_SECTION m_CriticalSection;
197 #endif
199 } tEplSdoComInstance;
201 //---------------------------------------------------------------------------
202 // modul globale vars
203 //---------------------------------------------------------------------------
204 static tEplSdoComInstance SdoComInstance_g;
205 //---------------------------------------------------------------------------
206 // local function prototypes
207 //---------------------------------------------------------------------------
208 tEplKernel EplSdoComReceiveCb(tEplSdoSeqConHdl SdoSeqConHdl_p,
209 tEplAsySdoCom *pAsySdoCom_p,
210 unsigned int uiDataSize_p);
212 tEplKernel EplSdoComConCb(tEplSdoSeqConHdl SdoSeqConHdl_p,
213 tEplAsySdoConState AsySdoConState_p);
215 static tEplKernel EplSdoComSearchConIntern(tEplSdoSeqConHdl SdoSeqConHdl_p,
216 tEplSdoComConEvent SdoComConEvent_p,
217 tEplAsySdoCom * pAsySdoCom_p);
219 static tEplKernel EplSdoComProcessIntern(tEplSdoComConHdl SdoComCon_p,
220 tEplSdoComConEvent SdoComConEvent_p,
221 tEplAsySdoCom * pAsySdoCom_p);
223 static tEplKernel EplSdoComTransferFinished(tEplSdoComConHdl SdoComCon_p,
224 tEplSdoComCon * pSdoComCon_p,
225 tEplSdoComConState
226 SdoComConState_p);
228 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
229 static tEplKernel EplSdoComServerInitReadByIndex(tEplSdoComCon * pSdoComCon_p,
230 tEplAsySdoCom * pAsySdoCom_p);
232 static tEplKernel EplSdoComServerSendFrameIntern(tEplSdoComCon * pSdoComCon_p,
233 unsigned int uiIndex_p,
234 unsigned int uiSubIndex_p,
235 tEplSdoComSendType SendType_p);
237 static tEplKernel EplSdoComServerInitWriteByIndex(tEplSdoComCon * pSdoComCon_p,
238 tEplAsySdoCom * pAsySdoCom_p);
239 #endif
241 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
243 static tEplKernel EplSdoComClientSend(tEplSdoComCon * pSdoComCon_p);
245 static tEplKernel EplSdoComClientProcessFrame(tEplSdoComConHdl SdoComCon_p,
246 tEplAsySdoCom * pAsySdoCom_p);
248 static tEplKernel EplSdoComClientSendAbort(tEplSdoComCon * pSdoComCon_p,
249 DWORD dwAbortCode_p);
250 #endif
252 /***************************************************************************/
253 /* */
254 /* */
255 /* C L A S S <SDO Command Layer> */
256 /* */
257 /* */
258 /***************************************************************************/
260 // Description: SDO Command layer Modul
263 /***************************************************************************/
265 //=========================================================================//
266 // //
267 // P U B L I C F U N C T I O N S //
268 // //
269 //=========================================================================//
271 //---------------------------------------------------------------------------
273 // Function: EplSdoComInit
275 // Description: Init first instance of the module
279 // Parameters:
282 // Returns: tEplKernel = errorcode
285 // State:
287 //---------------------------------------------------------------------------
288 tEplKernel EplSdoComInit(void)
290 tEplKernel Ret;
292 Ret = EplSdoComAddInstance();
294 return Ret;
298 //---------------------------------------------------------------------------
300 // Function: EplSdoComAddInstance
302 // Description: Init additional instance of the module
306 // Parameters:
309 // Returns: tEplKernel = errorcode
312 // State:
314 //---------------------------------------------------------------------------
315 tEplKernel EplSdoComAddInstance(void)
317 tEplKernel Ret;
319 Ret = kEplSuccessful;
321 // init controll structure
322 EPL_MEMSET(&SdoComInstance_g, 0x00, sizeof(SdoComInstance_g));
324 // init instance of lower layer
325 Ret = EplSdoAsySeqAddInstance(EplSdoComReceiveCb, EplSdoComConCb);
326 if (Ret != kEplSuccessful) {
327 goto Exit;
329 #if defined(WIN32) || defined(_WIN32)
330 // create critical section for process function
331 SdoComInstance_g.m_pCriticalSection =
332 &SdoComInstance_g.m_CriticalSection;
333 InitializeCriticalSection(SdoComInstance_g.m_pCriticalSection);
334 #endif
336 Exit:
337 return Ret;
340 //---------------------------------------------------------------------------
342 // Function: EplSdoComDelInstance
344 // Description: delete instance of the module
348 // Parameters:
351 // Returns: tEplKernel = errorcode
354 // State:
356 //---------------------------------------------------------------------------
357 tEplKernel EplSdoComDelInstance(void)
359 tEplKernel Ret;
361 Ret = kEplSuccessful;
363 #if defined(WIN32) || defined(_WIN32)
364 // delete critical section for process function
365 DeleteCriticalSection(SdoComInstance_g.m_pCriticalSection);
366 #endif
368 Ret = EplSdoAsySeqDelInstance();
369 if (Ret != kEplSuccessful) {
370 goto Exit;
373 Exit:
374 return Ret;
377 //---------------------------------------------------------------------------
379 // Function: EplSdoComDefineCon
381 // Description: function defines a SDO connection to another node
382 // -> init lower layer and returns a handle for the connection.
383 // Two client connections to the same node via the same protocol
384 // are not allowed. If this function detects such a situation
385 // it will return kEplSdoComHandleExists and the handle of
386 // the existing connection in pSdoComConHdl_p.
387 // Using of existing server connections is possible.
389 // Parameters: pSdoComConHdl_p = pointer to the buffer of the handle
390 // uiTargetNodeId_p = NodeId of the targetnode
391 // ProtType_p = type of protocol to use for connection
394 // Returns: tEplKernel = errorcode
397 // State:
399 //---------------------------------------------------------------------------
400 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
401 tEplKernel EplSdoComDefineCon(tEplSdoComConHdl *pSdoComConHdl_p,
402 unsigned int uiTargetNodeId_p,
403 tEplSdoType ProtType_p)
405 tEplKernel Ret;
406 unsigned int uiCount;
407 unsigned int uiFreeHdl;
408 tEplSdoComCon *pSdoComCon;
410 // check Parameter
411 ASSERT(pSdoComConHdl_p != NULL);
413 // check NodeId
414 if ((uiTargetNodeId_p == EPL_C_ADR_INVALID)
415 || (uiTargetNodeId_p >= EPL_C_ADR_BROADCAST)) {
416 Ret = kEplInvalidNodeId;
419 // search free control structure
420 pSdoComCon = &SdoComInstance_g.m_SdoComCon[0];
421 uiCount = 0;
422 uiFreeHdl = EPL_MAX_SDO_COM_CON;
423 while (uiCount < EPL_MAX_SDO_COM_CON) {
424 if (pSdoComCon->m_SdoSeqConHdl == 0) { // free entry
425 uiFreeHdl = uiCount;
426 } else if ((pSdoComCon->m_uiNodeId == uiTargetNodeId_p)
427 && (pSdoComCon->m_SdoProtType == ProtType_p)) { // existing client connection with same node ID and same protocol type
428 *pSdoComConHdl_p = uiCount;
429 Ret = kEplSdoComHandleExists;
430 goto Exit;
432 uiCount++;
433 pSdoComCon++;
436 if (uiFreeHdl == EPL_MAX_SDO_COM_CON) {
437 Ret = kEplSdoComNoFreeHandle;
438 goto Exit;
441 pSdoComCon = &SdoComInstance_g.m_SdoComCon[uiFreeHdl];
442 // save handle for application
443 *pSdoComConHdl_p = uiFreeHdl;
444 // save parameters
445 pSdoComCon->m_SdoProtType = ProtType_p;
446 pSdoComCon->m_uiNodeId = uiTargetNodeId_p;
448 // set Transaction Id
449 pSdoComCon->m_bTransactionId = 0;
451 // check protocol
452 switch (ProtType_p) {
453 // udp
454 case kEplSdoTypeUdp:
456 // call connection int function of lower layer
457 Ret = EplSdoAsySeqInitCon(&pSdoComCon->m_SdoSeqConHdl,
458 pSdoComCon->m_uiNodeId,
459 kEplSdoTypeUdp);
460 if (Ret != kEplSuccessful) {
461 goto Exit;
463 break;
466 // Asend
467 case kEplSdoTypeAsnd:
469 // call connection int function of lower layer
470 Ret = EplSdoAsySeqInitCon(&pSdoComCon->m_SdoSeqConHdl,
471 pSdoComCon->m_uiNodeId,
472 kEplSdoTypeAsnd);
473 if (Ret != kEplSuccessful) {
474 goto Exit;
476 break;
479 // Pdo -> not supported
480 case kEplSdoTypePdo:
481 default:
483 Ret = kEplSdoComUnsupportedProt;
484 goto Exit;
486 } // end of switch(m_ProtType_p)
488 // call process function
489 Ret = EplSdoComProcessIntern(uiFreeHdl,
490 kEplSdoComConEventInitCon, NULL);
492 Exit:
493 return Ret;
495 #endif
496 //---------------------------------------------------------------------------
498 // Function: EplSdoComInitTransferByIndex
500 // Description: function init SDO Transfer for a defined connection
504 // Parameters: SdoComTransParam_p = Structure with parameters for connection
507 // Returns: tEplKernel = errorcode
510 // State:
512 //---------------------------------------------------------------------------
513 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
514 tEplKernel EplSdoComInitTransferByIndex(tEplSdoComTransParamByIndex *pSdoComTransParam_p)
516 tEplKernel Ret;
517 tEplSdoComCon *pSdoComCon;
519 // check parameter
520 if ((pSdoComTransParam_p->m_uiSubindex >= 0xFF)
521 || (pSdoComTransParam_p->m_uiIndex == 0)
522 || (pSdoComTransParam_p->m_uiIndex > 0xFFFF)
523 || (pSdoComTransParam_p->m_pData == NULL)
524 || (pSdoComTransParam_p->m_uiDataSize == 0)) {
525 Ret = kEplSdoComInvalidParam;
526 goto Exit;
529 if (pSdoComTransParam_p->m_SdoComConHdl >= EPL_MAX_SDO_COM_CON) {
530 Ret = kEplSdoComInvalidHandle;
531 goto Exit;
533 // get pointer to control structure of connection
534 pSdoComCon =
535 &SdoComInstance_g.m_SdoComCon[pSdoComTransParam_p->m_SdoComConHdl];
537 // check if handle ok
538 if (pSdoComCon->m_SdoSeqConHdl == 0) {
539 Ret = kEplSdoComInvalidHandle;
540 goto Exit;
542 // check if command layer is idle
543 if ((pSdoComCon->m_uiTransferredByte + pSdoComCon->m_uiTransSize) > 0) { // handle is not idle
544 Ret = kEplSdoComHandleBusy;
545 goto Exit;
547 // save parameter
548 // callback function for end of transfer
549 pSdoComCon->m_pfnTransferFinished =
550 pSdoComTransParam_p->m_pfnSdoFinishedCb;
551 pSdoComCon->m_pUserArg = pSdoComTransParam_p->m_pUserArg;
553 // set type of SDO command
554 if (pSdoComTransParam_p->m_SdoAccessType == kEplSdoAccessTypeRead) {
555 pSdoComCon->m_SdoServiceType = kEplSdoServiceReadByIndex;
556 } else {
557 pSdoComCon->m_SdoServiceType = kEplSdoServiceWriteByIndex;
560 // save pointer to data
561 pSdoComCon->m_pData = pSdoComTransParam_p->m_pData;
562 // maximal bytes to transfer
563 pSdoComCon->m_uiTransSize = pSdoComTransParam_p->m_uiDataSize;
564 // bytes already transfered
565 pSdoComCon->m_uiTransferredByte = 0;
567 // reset parts of control structure
568 pSdoComCon->m_dwLastAbortCode = 0;
569 pSdoComCon->m_SdoTransType = kEplSdoTransAuto;
570 // save timeout
571 //pSdoComCon->m_uiTimeout = SdoComTransParam_p.m_uiTimeout;
573 // save index and subindex
574 pSdoComCon->m_uiTargetIndex = pSdoComTransParam_p->m_uiIndex;
575 pSdoComCon->m_uiTargetSubIndex = pSdoComTransParam_p->m_uiSubindex;
577 // call process function
578 Ret = EplSdoComProcessIntern(pSdoComTransParam_p->m_SdoComConHdl, kEplSdoComConEventSendFirst, // event to start transfer
579 NULL);
581 Exit:
582 return Ret;
585 #endif
587 //---------------------------------------------------------------------------
589 // Function: EplSdoComUndefineCon
591 // Description: function undefine a SDO connection
595 // Parameters: SdoComConHdl_p = handle for the connection
598 // Returns: tEplKernel = errorcode
601 // State:
603 //---------------------------------------------------------------------------
604 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
605 tEplKernel EplSdoComUndefineCon(tEplSdoComConHdl SdoComConHdl_p)
607 tEplKernel Ret;
608 tEplSdoComCon *pSdoComCon;
610 Ret = kEplSuccessful;
612 if (SdoComConHdl_p >= EPL_MAX_SDO_COM_CON) {
613 Ret = kEplSdoComInvalidHandle;
614 goto Exit;
616 // get pointer to control structure
617 pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComConHdl_p];
619 // $$$ d.k. abort a running transfer before closing the sequence layer
621 if (((pSdoComCon->m_SdoSeqConHdl & ~EPL_SDO_SEQ_HANDLE_MASK) !=
622 EPL_SDO_SEQ_INVALID_HDL)
623 && (pSdoComCon->m_SdoSeqConHdl != 0)) {
624 // close connection in lower layer
625 switch (pSdoComCon->m_SdoProtType) {
626 case kEplSdoTypeAsnd:
627 case kEplSdoTypeUdp:
629 Ret =
630 EplSdoAsySeqDelCon(pSdoComCon->
631 m_SdoSeqConHdl);
632 break;
635 case kEplSdoTypePdo:
636 case kEplSdoTypeAuto:
637 default:
639 Ret = kEplSdoComUnsupportedProt;
640 goto Exit;
643 } // end of switch(pSdoComCon->m_SdoProtType)
646 // clean controll structure
647 EPL_MEMSET(pSdoComCon, 0x00, sizeof(tEplSdoComCon));
648 Exit:
649 return Ret;
651 #endif
652 //---------------------------------------------------------------------------
654 // Function: EplSdoComGetState
656 // Description: function returns the state fo the connection
660 // Parameters: SdoComConHdl_p = handle for the connection
661 // pSdoComFinished_p = pointer to structur for sdo state
664 // Returns: tEplKernel = errorcode
667 // State:
669 //---------------------------------------------------------------------------
670 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
671 tEplKernel EplSdoComGetState(tEplSdoComConHdl SdoComConHdl_p,
672 tEplSdoComFinished *pSdoComFinished_p)
674 tEplKernel Ret;
675 tEplSdoComCon *pSdoComCon;
677 Ret = kEplSuccessful;
679 if (SdoComConHdl_p >= EPL_MAX_SDO_COM_CON) {
680 Ret = kEplSdoComInvalidHandle;
681 goto Exit;
683 // get pointer to control structure
684 pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComConHdl_p];
686 // check if handle ok
687 if (pSdoComCon->m_SdoSeqConHdl == 0) {
688 Ret = kEplSdoComInvalidHandle;
689 goto Exit;
692 pSdoComFinished_p->m_pUserArg = pSdoComCon->m_pUserArg;
693 pSdoComFinished_p->m_uiNodeId = pSdoComCon->m_uiNodeId;
694 pSdoComFinished_p->m_uiTargetIndex = pSdoComCon->m_uiTargetIndex;
695 pSdoComFinished_p->m_uiTargetSubIndex = pSdoComCon->m_uiTargetSubIndex;
696 pSdoComFinished_p->m_uiTransferredByte =
697 pSdoComCon->m_uiTransferredByte;
698 pSdoComFinished_p->m_dwAbortCode = pSdoComCon->m_dwLastAbortCode;
699 pSdoComFinished_p->m_SdoComConHdl = SdoComConHdl_p;
700 if (pSdoComCon->m_SdoServiceType == kEplSdoServiceWriteByIndex) {
701 pSdoComFinished_p->m_SdoAccessType = kEplSdoAccessTypeWrite;
702 } else {
703 pSdoComFinished_p->m_SdoAccessType = kEplSdoAccessTypeRead;
706 if (pSdoComCon->m_dwLastAbortCode != 0) { // sdo abort
707 pSdoComFinished_p->m_SdoComConState =
708 kEplSdoComTransferRxAborted;
710 // delete abort code
711 pSdoComCon->m_dwLastAbortCode = 0;
713 } else if ((pSdoComCon->m_SdoSeqConHdl & ~EPL_SDO_SEQ_HANDLE_MASK) == EPL_SDO_SEQ_INVALID_HDL) { // check state
714 pSdoComFinished_p->m_SdoComConState =
715 kEplSdoComTransferLowerLayerAbort;
716 } else if (pSdoComCon->m_SdoComState == kEplSdoComStateClientWaitInit) {
717 // finished
718 pSdoComFinished_p->m_SdoComConState =
719 kEplSdoComTransferNotActive;
720 } else if (pSdoComCon->m_uiTransSize == 0) { // finished
721 pSdoComFinished_p->m_SdoComConState =
722 kEplSdoComTransferFinished;
725 Exit:
726 return Ret;
729 #endif
730 //---------------------------------------------------------------------------
732 // Function: EplSdoComSdoAbort
734 // Description: function abort a sdo transfer
738 // Parameters: SdoComConHdl_p = handle for the connection
739 // dwAbortCode_p = abort code
742 // Returns: tEplKernel = errorcode
745 // State:
747 //---------------------------------------------------------------------------
748 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
749 tEplKernel EplSdoComSdoAbort(tEplSdoComConHdl SdoComConHdl_p,
750 DWORD dwAbortCode_p)
752 tEplKernel Ret;
753 tEplSdoComCon *pSdoComCon;
755 if (SdoComConHdl_p >= EPL_MAX_SDO_COM_CON) {
756 Ret = kEplSdoComInvalidHandle;
757 goto Exit;
759 // get pointer to control structure of connection
760 pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComConHdl_p];
762 // check if handle ok
763 if (pSdoComCon->m_SdoSeqConHdl == 0) {
764 Ret = kEplSdoComInvalidHandle;
765 goto Exit;
767 // save pointer to abort code
768 pSdoComCon->m_pData = (BYTE *) & dwAbortCode_p;
770 Ret = EplSdoComProcessIntern(SdoComConHdl_p,
771 kEplSdoComConEventAbort,
772 (tEplAsySdoCom *) NULL);
774 Exit:
775 return Ret;
777 #endif
779 //=========================================================================//
780 // //
781 // P R I V A T E F U N C T I O N S //
782 // //
783 //=========================================================================//
785 //---------------------------------------------------------------------------
787 // Function: EplSdoComReceiveCb
789 // Description: callback function for SDO Sequence Layer
790 // -> indicates new data
794 // Parameters: SdoSeqConHdl_p = Handle for connection
795 // pAsySdoCom_p = pointer to data
796 // uiDataSize_p = size of data ($$$ not used yet, but it should)
799 // Returns:
802 // State:
804 //---------------------------------------------------------------------------
805 tEplKernel EplSdoComReceiveCb(tEplSdoSeqConHdl SdoSeqConHdl_p,
806 tEplAsySdoCom *pAsySdoCom_p,
807 unsigned int uiDataSize_p)
809 tEplKernel Ret;
811 // search connection internally
812 Ret = EplSdoComSearchConIntern(SdoSeqConHdl_p,
813 kEplSdoComConEventRec, pAsySdoCom_p);
815 EPL_DBGLVL_SDO_TRACE3
816 ("EplSdoComReceiveCb SdoSeqConHdl: 0x%X, First Byte of pAsySdoCom_p: 0x%02X, uiDataSize_p: 0x%04X\n",
817 SdoSeqConHdl_p, (WORD) pAsySdoCom_p->m_le_abCommandData[0],
818 uiDataSize_p);
820 return Ret;
823 //---------------------------------------------------------------------------
825 // Function: EplSdoComConCb
827 // Description: callback function called by SDO Sequence Layer to inform
828 // command layer about state change of connection
832 // Parameters: SdoSeqConHdl_p = Handle of the connection
833 // AsySdoConState_p = Event of the connection
836 // Returns: tEplKernel = Errorcode
839 // State:
841 //---------------------------------------------------------------------------
842 tEplKernel EplSdoComConCb(tEplSdoSeqConHdl SdoSeqConHdl_p,
843 tEplAsySdoConState AsySdoConState_p)
845 tEplKernel Ret;
846 tEplSdoComConEvent SdoComConEvent = kEplSdoComConEventSendFirst;
848 Ret = kEplSuccessful;
850 // check state
851 switch (AsySdoConState_p) {
852 case kAsySdoConStateConnected:
854 EPL_DBGLVL_SDO_TRACE0("Connection established\n");
855 SdoComConEvent = kEplSdoComConEventConEstablished;
856 // start transmission if needed
857 break;
860 case kAsySdoConStateInitError:
862 EPL_DBGLVL_SDO_TRACE0("Error during initialisation\n");
863 SdoComConEvent = kEplSdoComConEventInitError;
864 // inform app about error and close sequence layer handle
865 break;
868 case kAsySdoConStateConClosed:
870 EPL_DBGLVL_SDO_TRACE0("Connection closed\n");
871 SdoComConEvent = kEplSdoComConEventConClosed;
872 // close sequence layer handle
873 break;
876 case kAsySdoConStateAckReceived:
878 EPL_DBGLVL_SDO_TRACE0("Acknowlage received\n");
879 SdoComConEvent = kEplSdoComConEventAckReceived;
880 // continue transmission
881 break;
884 case kAsySdoConStateFrameSended:
886 EPL_DBGLVL_SDO_TRACE0("One Frame sent\n");
887 SdoComConEvent = kEplSdoComConEventFrameSended;
888 // to continue transmission
889 break;
893 case kAsySdoConStateTimeout:
895 EPL_DBGLVL_SDO_TRACE0("Timeout\n");
896 SdoComConEvent = kEplSdoComConEventTimeout;
897 // close sequence layer handle
898 break;
901 } // end of switch(AsySdoConState_p)
903 Ret = EplSdoComSearchConIntern(SdoSeqConHdl_p,
904 SdoComConEvent, (tEplAsySdoCom *) NULL);
906 return Ret;
909 //---------------------------------------------------------------------------
911 // Function: EplSdoComSearchConIntern
913 // Description: search a Sdo Sequence Layer connection handle in the
914 // control structure of the Command Layer
916 // Parameters: SdoSeqConHdl_p = Handle to search
917 // SdoComConEvent_p = event to process
918 // pAsySdoCom_p = pointer to received frame
920 // Returns: tEplKernel
923 // State:
925 //---------------------------------------------------------------------------
926 static tEplKernel EplSdoComSearchConIntern(tEplSdoSeqConHdl SdoSeqConHdl_p,
927 tEplSdoComConEvent SdoComConEvent_p,
928 tEplAsySdoCom * pAsySdoCom_p)
930 tEplKernel Ret;
931 tEplSdoComCon *pSdoComCon;
932 tEplSdoComConHdl HdlCount;
933 tEplSdoComConHdl HdlFree;
935 Ret = kEplSdoComNotResponsible;
937 // get pointer to first element of the array
938 pSdoComCon = &SdoComInstance_g.m_SdoComCon[0];
939 HdlCount = 0;
940 HdlFree = 0xFFFF;
941 while (HdlCount < EPL_MAX_SDO_COM_CON) {
942 if (pSdoComCon->m_SdoSeqConHdl == SdoSeqConHdl_p) { // matching command layer handle found
943 Ret = EplSdoComProcessIntern(HdlCount,
944 SdoComConEvent_p,
945 pAsySdoCom_p);
946 } else if ((pSdoComCon->m_SdoSeqConHdl == 0)
947 && (HdlFree == 0xFFFF)) {
948 HdlFree = HdlCount;
951 pSdoComCon++;
952 HdlCount++;
955 if (Ret == kEplSdoComNotResponsible) { // no responsible command layer handle found
956 if (HdlFree == 0xFFFF) { // no free handle
957 // delete connection immediately
958 // 2008/04/14 m.u./d.k. This connection actually does not exist.
959 // pSdoComCon is invalid.
960 // Ret = EplSdoAsySeqDelCon(pSdoComCon->m_SdoSeqConHdl);
961 Ret = kEplSdoComNoFreeHandle;
962 } else { // create new handle
963 HdlCount = HdlFree;
964 pSdoComCon = &SdoComInstance_g.m_SdoComCon[HdlCount];
965 pSdoComCon->m_SdoSeqConHdl = SdoSeqConHdl_p;
966 Ret = EplSdoComProcessIntern(HdlCount,
967 SdoComConEvent_p,
968 pAsySdoCom_p);
972 return Ret;
976 //---------------------------------------------------------------------------
978 // Function: EplSdoComProcessIntern
980 // Description: search a Sdo Sequence Layer connection handle in the
981 // control structer of the Command Layer
985 // Parameters: SdoComCon_p = index of control structure of connection
986 // SdoComConEvent_p = event to process
987 // pAsySdoCom_p = pointer to received frame
989 // Returns: tEplKernel = errorcode
992 // State:
994 //---------------------------------------------------------------------------
995 static tEplKernel EplSdoComProcessIntern(tEplSdoComConHdl SdoComCon_p,
996 tEplSdoComConEvent SdoComConEvent_p,
997 tEplAsySdoCom * pAsySdoCom_p)
999 tEplKernel Ret;
1000 tEplSdoComCon *pSdoComCon;
1001 BYTE bFlag;
1003 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
1004 DWORD dwAbortCode;
1005 unsigned int uiSize;
1006 #endif
1008 #if defined(WIN32) || defined(_WIN32)
1009 // enter critical section for process function
1010 EnterCriticalSection(SdoComInstance_g.m_pCriticalSection);
1011 EPL_DBGLVL_SDO_TRACE0
1012 ("\n\tEnterCiticalSection EplSdoComProcessIntern\n\n");
1013 #endif
1015 Ret = kEplSuccessful;
1017 // get pointer to control structure
1018 pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComCon_p];
1020 // process state maschine
1021 switch (pSdoComCon->m_SdoComState) {
1022 // idle state
1023 case kEplSdoComStateIdle:
1025 // check events
1026 switch (SdoComConEvent_p) {
1027 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
1028 // init con for client
1029 case kEplSdoComConEventInitCon:
1032 // call of the init function already
1033 // processed in EplSdoComDefineCon()
1034 // only change state to kEplSdoComStateClientWaitInit
1035 pSdoComCon->m_SdoComState =
1036 kEplSdoComStateClientWaitInit;
1037 break;
1039 #endif
1041 // int con for server
1042 case kEplSdoComConEventRec:
1044 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
1045 // check if init of an transfer and no SDO abort
1046 if ((pAsySdoCom_p->m_le_bFlags & 0x80) == 0) { // SDO request
1047 if ((pAsySdoCom_p->m_le_bFlags & 0x40) == 0) { // no SDO abort
1048 // save tansaction id
1049 pSdoComCon->
1050 m_bTransactionId =
1051 AmiGetByteFromLe
1052 (&pAsySdoCom_p->
1053 m_le_bTransactionId);
1054 // check command
1055 switch (pAsySdoCom_p->
1056 m_le_bCommandId)
1058 case kEplSdoServiceNIL:
1059 { // simply acknowlegde NIL command on sequence layer
1061 Ret =
1062 EplSdoAsySeqSendData
1063 (pSdoComCon->
1064 m_SdoSeqConHdl,
1066 (tEplFrame
1068 NULL);
1070 break;
1073 case kEplSdoServiceReadByIndex:
1074 { // read by index
1076 // search entry an start transfer
1077 EplSdoComServerInitReadByIndex
1078 (pSdoComCon,
1079 pAsySdoCom_p);
1080 // check next state
1081 if (pSdoComCon->m_uiTransSize == 0) { // ready -> stay idle
1082 pSdoComCon->
1083 m_SdoComState
1085 kEplSdoComStateIdle;
1086 // reset abort code
1087 pSdoComCon->
1088 m_dwLastAbortCode
1091 } else { // segmented transfer
1092 pSdoComCon->
1093 m_SdoComState
1095 kEplSdoComStateServerSegmTrans;
1098 break;
1101 case kEplSdoServiceWriteByIndex:
1104 // search entry an start write
1105 EplSdoComServerInitWriteByIndex
1106 (pSdoComCon,
1107 pAsySdoCom_p);
1108 // check next state
1109 if (pSdoComCon->m_uiTransSize == 0) { // already -> stay idle
1110 pSdoComCon->
1111 m_SdoComState
1113 kEplSdoComStateIdle;
1114 // reset abort code
1115 pSdoComCon->
1116 m_dwLastAbortCode
1119 } else { // segmented transfer
1120 pSdoComCon->
1121 m_SdoComState
1123 kEplSdoComStateServerSegmTrans;
1126 break;
1129 default:
1131 // unsupported command
1132 // -> abort senden
1133 dwAbortCode
1135 EPL_SDOAC_UNKNOWN_COMMAND_SPECIFIER;
1136 // send abort
1137 pSdoComCon->
1138 m_pData
1140 (BYTE
1143 dwAbortCode;
1144 Ret =
1145 EplSdoComServerSendFrameIntern
1146 (pSdoComCon,
1149 kEplSdoComSendTypeAbort);
1153 } // end of switch(pAsySdoCom_p->m_le_bCommandId)
1155 } else { // this command layer handle is not responsible
1156 // (wrong direction or wrong transaction ID)
1157 Ret = kEplSdoComNotResponsible;
1158 goto Exit;
1160 #endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
1162 break;
1165 // connection closed
1166 case kEplSdoComConEventInitError:
1167 case kEplSdoComConEventTimeout:
1168 case kEplSdoComConEventConClosed:
1170 Ret =
1171 EplSdoAsySeqDelCon(pSdoComCon->
1172 m_SdoSeqConHdl);
1173 // clean control structure
1174 EPL_MEMSET(pSdoComCon, 0x00,
1175 sizeof(tEplSdoComCon));
1176 break;
1179 default:
1180 // d.k. do nothing
1181 break;
1182 } // end of switch(SdoComConEvent_p)
1183 break;
1186 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
1187 //-------------------------------------------------------------------------
1188 // SDO Server part
1189 // segmented transfer
1190 case kEplSdoComStateServerSegmTrans:
1192 // check events
1193 switch (SdoComConEvent_p) {
1194 // send next frame
1195 case kEplSdoComConEventAckReceived:
1196 case kEplSdoComConEventFrameSended:
1198 // check if it is a read
1199 if (pSdoComCon->m_SdoServiceType ==
1200 kEplSdoServiceReadByIndex) {
1201 // send next frame
1202 EplSdoComServerSendFrameIntern
1203 (pSdoComCon, 0, 0,
1204 kEplSdoComSendTypeRes);
1205 // if all send -> back to idle
1206 if (pSdoComCon->m_uiTransSize == 0) { // back to idle
1207 pSdoComCon->
1208 m_SdoComState =
1209 kEplSdoComStateIdle;
1210 // reset abort code
1211 pSdoComCon->
1212 m_dwLastAbortCode =
1217 break;
1220 // process next frame
1221 case kEplSdoComConEventRec:
1223 // check if the frame is a SDO response and has the right transaction ID
1224 bFlag =
1225 AmiGetByteFromLe(&pAsySdoCom_p->
1226 m_le_bFlags);
1227 if (((bFlag & 0x80) != 0)
1229 (AmiGetByteFromLe
1230 (&pAsySdoCom_p->
1231 m_le_bTransactionId) ==
1232 pSdoComCon->m_bTransactionId)) {
1233 // check if it is a abort
1234 if ((bFlag & 0x40) != 0) { // SDO abort
1235 // clear control structure
1236 pSdoComCon->
1237 m_uiTransSize = 0;
1238 pSdoComCon->
1239 m_uiTransferredByte
1240 = 0;
1241 // change state
1242 pSdoComCon->
1243 m_SdoComState =
1244 kEplSdoComStateIdle;
1245 // reset abort code
1246 pSdoComCon->
1247 m_dwLastAbortCode =
1249 // d.k.: do not execute anything further on this command
1250 break;
1252 // check if it is a write
1253 if (pSdoComCon->
1254 m_SdoServiceType ==
1255 kEplSdoServiceWriteByIndex)
1257 // write data to OD
1258 uiSize =
1259 AmiGetWordFromLe
1260 (&pAsySdoCom_p->
1261 m_le_wSegmentSize);
1262 if (pSdoComCon->
1263 m_dwLastAbortCode ==
1264 0) {
1265 EPL_MEMCPY
1266 (pSdoComCon->
1267 m_pData,
1268 &pAsySdoCom_p->
1269 m_le_abCommandData
1270 [0],
1271 uiSize);
1273 // update counter
1274 pSdoComCon->
1275 m_uiTransferredByte
1276 += uiSize;
1277 pSdoComCon->
1278 m_uiTransSize -=
1279 uiSize;
1281 // update pointer
1282 if (pSdoComCon->
1283 m_dwLastAbortCode ==
1284 0) {
1285 ( /*(BYTE*) */
1286 pSdoComCon->
1287 m_pData) +=
1288 uiSize;
1290 // check end of transfer
1291 if ((pAsySdoCom_p->m_le_bFlags & 0x30) == 0x30) { // transfer ready
1292 pSdoComCon->
1293 m_uiTransSize
1294 = 0;
1296 if (pSdoComCon->
1297 m_dwLastAbortCode
1298 == 0) {
1299 // send response
1300 // send next frame
1301 EplSdoComServerSendFrameIntern
1302 (pSdoComCon,
1305 kEplSdoComSendTypeRes);
1306 // if all send -> back to idle
1307 if (pSdoComCon->m_uiTransSize == 0) { // back to idle
1308 pSdoComCon->
1309 m_SdoComState
1311 kEplSdoComStateIdle;
1312 // reset abort code
1313 pSdoComCon->
1314 m_dwLastAbortCode
1318 } else { // send dabort code
1319 // send abort
1320 pSdoComCon->
1321 m_pData
1323 (BYTE
1326 pSdoComCon->
1327 m_dwLastAbortCode;
1328 Ret =
1329 EplSdoComServerSendFrameIntern
1330 (pSdoComCon,
1333 kEplSdoComSendTypeAbort);
1335 // reset abort code
1336 pSdoComCon->
1337 m_dwLastAbortCode
1338 = 0;
1341 } else {
1342 // send acknowledge without any Command layer data
1343 Ret =
1344 EplSdoAsySeqSendData
1345 (pSdoComCon->
1346 m_SdoSeqConHdl,
1348 (tEplFrame
1349 *) NULL);
1352 } else { // this command layer handle is not responsible
1353 // (wrong direction or wrong transaction ID)
1354 Ret = kEplSdoComNotResponsible;
1355 goto Exit;
1357 break;
1360 // connection closed
1361 case kEplSdoComConEventInitError:
1362 case kEplSdoComConEventTimeout:
1363 case kEplSdoComConEventConClosed:
1365 Ret =
1366 EplSdoAsySeqDelCon(pSdoComCon->
1367 m_SdoSeqConHdl);
1368 // clean control structure
1369 EPL_MEMSET(pSdoComCon, 0x00,
1370 sizeof(tEplSdoComCon));
1371 break;
1374 default:
1375 // d.k. do nothing
1376 break;
1377 } // end of switch(SdoComConEvent_p)
1379 break;
1381 #endif // endif of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
1383 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
1384 //-------------------------------------------------------------------------
1385 // SDO Client part
1386 // wait for finish of establishing connection
1387 case kEplSdoComStateClientWaitInit:
1390 // if connection handle is invalid reinit connection
1391 // d.k.: this will be done only on new events (i.e. InitTransfer)
1392 if ((pSdoComCon->
1393 m_SdoSeqConHdl & ~EPL_SDO_SEQ_HANDLE_MASK) ==
1394 EPL_SDO_SEQ_INVALID_HDL) {
1395 // check kind of connection to reinit
1396 // check protocol
1397 switch (pSdoComCon->m_SdoProtType) {
1398 // udp
1399 case kEplSdoTypeUdp:
1401 // call connection int function of lower layer
1402 Ret =
1403 EplSdoAsySeqInitCon
1404 (&pSdoComCon->
1405 m_SdoSeqConHdl,
1406 pSdoComCon->m_uiNodeId,
1407 kEplSdoTypeUdp);
1408 if (Ret != kEplSuccessful) {
1409 goto Exit;
1411 break;
1414 // Asend -> not supported
1415 case kEplSdoTypeAsnd:
1417 // call connection int function of lower layer
1418 Ret =
1419 EplSdoAsySeqInitCon
1420 (&pSdoComCon->
1421 m_SdoSeqConHdl,
1422 pSdoComCon->m_uiNodeId,
1423 kEplSdoTypeAsnd);
1424 if (Ret != kEplSuccessful) {
1425 goto Exit;
1427 break;
1430 // Pdo -> not supported
1431 case kEplSdoTypePdo:
1432 default:
1434 Ret = kEplSdoComUnsupportedProt;
1435 goto Exit;
1437 } // end of switch(m_ProtType_p)
1438 // d.k.: reset transaction ID, because new sequence layer connection was initialized
1439 // $$$ d.k. is this really necessary?
1440 //pSdoComCon->m_bTransactionId = 0;
1442 // check events
1443 switch (SdoComConEvent_p) {
1444 // connection established
1445 case kEplSdoComConEventConEstablished:
1447 //send first frame if needed
1448 if ((pSdoComCon->m_uiTransSize > 0)
1449 && (pSdoComCon->m_uiTargetIndex != 0)) { // start SDO transfer
1450 Ret =
1451 EplSdoComClientSend
1452 (pSdoComCon);
1453 if (Ret != kEplSuccessful) {
1454 goto Exit;
1456 // check if segemted transfer
1457 if (pSdoComCon->
1458 m_SdoTransType ==
1459 kEplSdoTransSegmented) {
1460 pSdoComCon->
1461 m_SdoComState =
1462 kEplSdoComStateClientSegmTrans;
1463 goto Exit;
1466 // goto state kEplSdoComStateClientConnected
1467 pSdoComCon->m_SdoComState =
1468 kEplSdoComStateClientConnected;
1469 goto Exit;
1472 case kEplSdoComConEventSendFirst:
1474 // infos for transfer already saved by function EplSdoComInitTransferByIndex
1475 break;
1478 case kEplSdoComConEventConClosed:
1479 case kEplSdoComConEventInitError:
1480 case kEplSdoComConEventTimeout:
1482 // close sequence layer handle
1483 Ret =
1484 EplSdoAsySeqDelCon(pSdoComCon->
1485 m_SdoSeqConHdl);
1486 pSdoComCon->m_SdoSeqConHdl |=
1487 EPL_SDO_SEQ_INVALID_HDL;
1488 // call callback function
1489 if (SdoComConEvent_p ==
1490 kEplSdoComConEventTimeout) {
1491 pSdoComCon->m_dwLastAbortCode =
1492 EPL_SDOAC_TIME_OUT;
1493 } else {
1494 pSdoComCon->m_dwLastAbortCode =
1497 Ret =
1498 EplSdoComTransferFinished
1499 (SdoComCon_p, pSdoComCon,
1500 kEplSdoComTransferLowerLayerAbort);
1501 // d.k.: do not clean control structure
1502 break;
1505 default:
1506 // d.k. do nothing
1507 break;
1509 } // end of switch(SdoComConEvent_p)
1510 break;
1513 // connected
1514 case kEplSdoComStateClientConnected:
1516 // check events
1517 switch (SdoComConEvent_p) {
1518 // send a frame
1519 case kEplSdoComConEventSendFirst:
1520 case kEplSdoComConEventAckReceived:
1521 case kEplSdoComConEventFrameSended:
1523 Ret = EplSdoComClientSend(pSdoComCon);
1524 if (Ret != kEplSuccessful) {
1525 goto Exit;
1527 // check if read transfer finished
1528 if ((pSdoComCon->m_uiTransSize == 0)
1529 && (pSdoComCon->
1530 m_uiTransferredByte != 0)
1531 && (pSdoComCon->m_SdoServiceType ==
1532 kEplSdoServiceReadByIndex)) {
1533 // inc transaction id
1534 pSdoComCon->m_bTransactionId++;
1535 // call callback of application
1536 pSdoComCon->m_dwLastAbortCode =
1538 Ret =
1539 EplSdoComTransferFinished
1540 (SdoComCon_p, pSdoComCon,
1541 kEplSdoComTransferFinished);
1543 goto Exit;
1545 // check if segemted transfer
1546 if (pSdoComCon->m_SdoTransType ==
1547 kEplSdoTransSegmented) {
1548 pSdoComCon->m_SdoComState =
1549 kEplSdoComStateClientSegmTrans;
1550 goto Exit;
1552 break;
1555 // frame received
1556 case kEplSdoComConEventRec:
1558 // check if the frame is a SDO response and has the right transaction ID
1559 bFlag =
1560 AmiGetByteFromLe(&pAsySdoCom_p->
1561 m_le_bFlags);
1562 if (((bFlag & 0x80) != 0)
1564 (AmiGetByteFromLe
1565 (&pAsySdoCom_p->
1566 m_le_bTransactionId) ==
1567 pSdoComCon->m_bTransactionId)) {
1568 // check if abort or not
1569 if ((bFlag & 0x40) != 0) {
1570 // send acknowledge without any Command layer data
1571 Ret =
1572 EplSdoAsySeqSendData
1573 (pSdoComCon->
1574 m_SdoSeqConHdl, 0,
1575 (tEplFrame *)
1576 NULL);
1577 // inc transaction id
1578 pSdoComCon->
1579 m_bTransactionId++;
1580 // save abort code
1581 pSdoComCon->
1582 m_dwLastAbortCode =
1583 AmiGetDwordFromLe
1584 (&pAsySdoCom_p->
1585 m_le_abCommandData
1586 [0]);
1587 // call callback of application
1588 Ret =
1589 EplSdoComTransferFinished
1590 (SdoComCon_p,
1591 pSdoComCon,
1592 kEplSdoComTransferRxAborted);
1594 goto Exit;
1595 } else { // normal frame received
1596 // check frame
1597 Ret =
1598 EplSdoComClientProcessFrame
1599 (SdoComCon_p,
1600 pAsySdoCom_p);
1602 // check if transfer ready
1603 if (pSdoComCon->
1604 m_uiTransSize ==
1605 0) {
1606 // send acknowledge without any Command layer data
1607 Ret =
1608 EplSdoAsySeqSendData
1609 (pSdoComCon->
1610 m_SdoSeqConHdl,
1612 (tEplFrame
1613 *) NULL);
1614 // inc transaction id
1615 pSdoComCon->
1616 m_bTransactionId++;
1617 // call callback of application
1618 pSdoComCon->
1619 m_dwLastAbortCode
1620 = 0;
1621 Ret =
1622 EplSdoComTransferFinished
1623 (SdoComCon_p,
1624 pSdoComCon,
1625 kEplSdoComTransferFinished);
1627 goto Exit;
1631 } else { // this command layer handle is not responsible
1632 // (wrong direction or wrong transaction ID)
1633 Ret = kEplSdoComNotResponsible;
1634 goto Exit;
1636 break;
1639 // connection closed event go back to kEplSdoComStateClientWaitInit
1640 case kEplSdoComConEventConClosed:
1641 { // connection closed by communication partner
1642 // close sequence layer handle
1643 Ret =
1644 EplSdoAsySeqDelCon(pSdoComCon->
1645 m_SdoSeqConHdl);
1646 // set handle to invalid and enter kEplSdoComStateClientWaitInit
1647 pSdoComCon->m_SdoSeqConHdl |=
1648 EPL_SDO_SEQ_INVALID_HDL;
1649 // change state
1650 pSdoComCon->m_SdoComState =
1651 kEplSdoComStateClientWaitInit;
1653 // call callback of application
1654 pSdoComCon->m_dwLastAbortCode = 0;
1655 Ret =
1656 EplSdoComTransferFinished
1657 (SdoComCon_p, pSdoComCon,
1658 kEplSdoComTransferLowerLayerAbort);
1660 goto Exit;
1662 break;
1665 // abort to send from higher layer
1666 case kEplSdoComConEventAbort:
1668 EplSdoComClientSendAbort(pSdoComCon,
1669 *((DWORD *)
1670 pSdoComCon->
1671 m_pData));
1673 // inc transaction id
1674 pSdoComCon->m_bTransactionId++;
1675 // call callback of application
1676 pSdoComCon->m_dwLastAbortCode =
1677 *((DWORD *) pSdoComCon->m_pData);
1678 Ret =
1679 EplSdoComTransferFinished
1680 (SdoComCon_p, pSdoComCon,
1681 kEplSdoComTransferTxAborted);
1683 break;
1686 case kEplSdoComConEventInitError:
1687 case kEplSdoComConEventTimeout:
1689 // close sequence layer handle
1690 Ret =
1691 EplSdoAsySeqDelCon(pSdoComCon->
1692 m_SdoSeqConHdl);
1693 pSdoComCon->m_SdoSeqConHdl |=
1694 EPL_SDO_SEQ_INVALID_HDL;
1695 // change state
1696 pSdoComCon->m_SdoComState =
1697 kEplSdoComStateClientWaitInit;
1698 // call callback of application
1699 pSdoComCon->m_dwLastAbortCode =
1700 EPL_SDOAC_TIME_OUT;
1701 Ret =
1702 EplSdoComTransferFinished
1703 (SdoComCon_p, pSdoComCon,
1704 kEplSdoComTransferLowerLayerAbort);
1708 default:
1709 // d.k. do nothing
1710 break;
1712 } // end of switch(SdoComConEvent_p)
1714 break;
1717 // process segmented transfer
1718 case kEplSdoComStateClientSegmTrans:
1720 // check events
1721 switch (SdoComConEvent_p) {
1722 // sned a frame
1723 case kEplSdoComConEventSendFirst:
1724 case kEplSdoComConEventAckReceived:
1725 case kEplSdoComConEventFrameSended:
1727 Ret = EplSdoComClientSend(pSdoComCon);
1728 if (Ret != kEplSuccessful) {
1729 goto Exit;
1731 // check if read transfer finished
1732 if ((pSdoComCon->m_uiTransSize == 0)
1733 && (pSdoComCon->m_SdoServiceType ==
1734 kEplSdoServiceReadByIndex)) {
1735 // inc transaction id
1736 pSdoComCon->m_bTransactionId++;
1737 // change state
1738 pSdoComCon->m_SdoComState =
1739 kEplSdoComStateClientConnected;
1740 // call callback of application
1741 pSdoComCon->m_dwLastAbortCode =
1743 Ret =
1744 EplSdoComTransferFinished
1745 (SdoComCon_p, pSdoComCon,
1746 kEplSdoComTransferFinished);
1748 goto Exit;
1751 break;
1754 // frame received
1755 case kEplSdoComConEventRec:
1757 // check if the frame is a response
1758 bFlag =
1759 AmiGetByteFromLe(&pAsySdoCom_p->
1760 m_le_bFlags);
1761 if (((bFlag & 0x80) != 0)
1763 (AmiGetByteFromLe
1764 (&pAsySdoCom_p->
1765 m_le_bTransactionId) ==
1766 pSdoComCon->m_bTransactionId)) {
1767 // check if abort or not
1768 if ((bFlag & 0x40) != 0) {
1769 // send acknowledge without any Command layer data
1770 Ret =
1771 EplSdoAsySeqSendData
1772 (pSdoComCon->
1773 m_SdoSeqConHdl, 0,
1774 (tEplFrame *)
1775 NULL);
1776 // inc transaction id
1777 pSdoComCon->
1778 m_bTransactionId++;
1779 // change state
1780 pSdoComCon->
1781 m_SdoComState =
1782 kEplSdoComStateClientConnected;
1783 // save abort code
1784 pSdoComCon->
1785 m_dwLastAbortCode =
1786 AmiGetDwordFromLe
1787 (&pAsySdoCom_p->
1788 m_le_abCommandData
1789 [0]);
1790 // call callback of application
1791 Ret =
1792 EplSdoComTransferFinished
1793 (SdoComCon_p,
1794 pSdoComCon,
1795 kEplSdoComTransferRxAborted);
1797 goto Exit;
1798 } else { // normal frame received
1799 // check frame
1800 Ret =
1801 EplSdoComClientProcessFrame
1802 (SdoComCon_p,
1803 pAsySdoCom_p);
1805 // check if transfer ready
1806 if (pSdoComCon->
1807 m_uiTransSize ==
1808 0) {
1809 // send acknowledge without any Command layer data
1810 Ret =
1811 EplSdoAsySeqSendData
1812 (pSdoComCon->
1813 m_SdoSeqConHdl,
1815 (tEplFrame
1816 *) NULL);
1817 // inc transaction id
1818 pSdoComCon->
1819 m_bTransactionId++;
1820 // change state
1821 pSdoComCon->
1822 m_SdoComState
1824 kEplSdoComStateClientConnected;
1825 // call callback of application
1826 pSdoComCon->
1827 m_dwLastAbortCode
1828 = 0;
1829 Ret =
1830 EplSdoComTransferFinished
1831 (SdoComCon_p,
1832 pSdoComCon,
1833 kEplSdoComTransferFinished);
1839 break;
1842 // connection closed event go back to kEplSdoComStateClientWaitInit
1843 case kEplSdoComConEventConClosed:
1844 { // connection closed by communication partner
1845 // close sequence layer handle
1846 Ret =
1847 EplSdoAsySeqDelCon(pSdoComCon->
1848 m_SdoSeqConHdl);
1849 // set handle to invalid and enter kEplSdoComStateClientWaitInit
1850 pSdoComCon->m_SdoSeqConHdl |=
1851 EPL_SDO_SEQ_INVALID_HDL;
1852 // change state
1853 pSdoComCon->m_SdoComState =
1854 kEplSdoComStateClientWaitInit;
1855 // inc transaction id
1856 pSdoComCon->m_bTransactionId++;
1857 // call callback of application
1858 pSdoComCon->m_dwLastAbortCode = 0;
1859 Ret =
1860 EplSdoComTransferFinished
1861 (SdoComCon_p, pSdoComCon,
1862 kEplSdoComTransferFinished);
1864 break;
1867 // abort to send from higher layer
1868 case kEplSdoComConEventAbort:
1870 EplSdoComClientSendAbort(pSdoComCon,
1871 *((DWORD *)
1872 pSdoComCon->
1873 m_pData));
1875 // inc transaction id
1876 pSdoComCon->m_bTransactionId++;
1877 // change state
1878 pSdoComCon->m_SdoComState =
1879 kEplSdoComStateClientConnected;
1880 // call callback of application
1881 pSdoComCon->m_dwLastAbortCode =
1882 *((DWORD *) pSdoComCon->m_pData);
1883 Ret =
1884 EplSdoComTransferFinished
1885 (SdoComCon_p, pSdoComCon,
1886 kEplSdoComTransferTxAborted);
1888 break;
1891 case kEplSdoComConEventInitError:
1892 case kEplSdoComConEventTimeout:
1894 // close sequence layer handle
1895 Ret =
1896 EplSdoAsySeqDelCon(pSdoComCon->
1897 m_SdoSeqConHdl);
1898 pSdoComCon->m_SdoSeqConHdl |=
1899 EPL_SDO_SEQ_INVALID_HDL;
1900 // change state
1901 pSdoComCon->m_SdoComState =
1902 kEplSdoComStateClientWaitInit;
1903 // call callback of application
1904 pSdoComCon->m_dwLastAbortCode =
1905 EPL_SDOAC_TIME_OUT;
1906 Ret =
1907 EplSdoComTransferFinished
1908 (SdoComCon_p, pSdoComCon,
1909 kEplSdoComTransferLowerLayerAbort);
1913 default:
1914 // d.k. do nothing
1915 break;
1917 } // end of switch(SdoComConEvent_p)
1919 break;
1921 #endif // endo of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
1923 } // end of switch(pSdoComCon->m_SdoComState)
1925 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
1926 Exit:
1927 #endif
1929 #if defined(WIN32) || defined(_WIN32)
1930 // leave critical section for process function
1931 EPL_DBGLVL_SDO_TRACE0
1932 ("\n\tLeaveCriticalSection EplSdoComProcessIntern\n\n");
1933 LeaveCriticalSection(SdoComInstance_g.m_pCriticalSection);
1935 #endif
1937 return Ret;
1941 //---------------------------------------------------------------------------
1943 // Function: EplSdoComServerInitReadByIndex
1945 // Description: function start the processing of an read by index command
1949 // Parameters: pSdoComCon_p = pointer to control structure of connection
1950 // pAsySdoCom_p = pointer to received frame
1952 // Returns: tEplKernel = errorcode
1955 // State:
1957 //---------------------------------------------------------------------------
1958 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
1959 static tEplKernel EplSdoComServerInitReadByIndex(tEplSdoComCon * pSdoComCon_p,
1960 tEplAsySdoCom * pAsySdoCom_p)
1962 tEplKernel Ret;
1963 unsigned int uiIndex;
1964 unsigned int uiSubindex;
1965 tEplObdSize EntrySize;
1966 tEplObdAccess AccessType;
1967 DWORD dwAbortCode;
1969 dwAbortCode = 0;
1971 // a init of a read could not be a segmented transfer
1972 // -> no variable part of header
1974 // get index and subindex
1975 uiIndex = AmiGetWordFromLe(&pAsySdoCom_p->m_le_abCommandData[0]);
1976 uiSubindex = AmiGetByteFromLe(&pAsySdoCom_p->m_le_abCommandData[2]);
1978 // check accesstype of entry
1979 // existens of entry
1980 //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
1981 Ret = EplObduGetAccessType(uiIndex, uiSubindex, &AccessType);
1982 /*#else
1983 Ret = kEplObdSubindexNotExist;
1984 AccessType = 0;
1985 #endif*/
1986 if (Ret == kEplObdSubindexNotExist) { // subentry doesn't exist
1987 dwAbortCode = EPL_SDOAC_SUB_INDEX_NOT_EXIST;
1988 // send abort
1989 pSdoComCon_p->m_pData = (BYTE *) & dwAbortCode;
1990 Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
1991 uiIndex,
1992 uiSubindex,
1993 kEplSdoComSendTypeAbort);
1994 goto Exit;
1995 } else if (Ret != kEplSuccessful) { // entry doesn't exist
1996 dwAbortCode = EPL_SDOAC_OBJECT_NOT_EXIST;
1997 // send abort
1998 pSdoComCon_p->m_pData = (BYTE *) & dwAbortCode;
1999 Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
2000 uiIndex,
2001 uiSubindex,
2002 kEplSdoComSendTypeAbort);
2003 goto Exit;
2005 // compare accesstype must be read or const
2006 if (((AccessType & kEplObdAccRead) == 0)
2007 && ((AccessType & kEplObdAccConst) == 0)) {
2009 if ((AccessType & kEplObdAccWrite) != 0) {
2010 // entry read a write only object
2011 dwAbortCode = EPL_SDOAC_READ_TO_WRITE_ONLY_OBJ;
2012 } else {
2013 dwAbortCode = EPL_SDOAC_UNSUPPORTED_ACCESS;
2015 // send abort
2016 pSdoComCon_p->m_pData = (BYTE *) & dwAbortCode;
2017 Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
2018 uiIndex,
2019 uiSubindex,
2020 kEplSdoComSendTypeAbort);
2021 goto Exit;
2023 // save service
2024 pSdoComCon_p->m_SdoServiceType = kEplSdoServiceReadByIndex;
2026 // get size of object to see iof segmented or expedited transfer
2027 //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
2028 EntrySize = EplObduGetDataSize(uiIndex, uiSubindex);
2029 /*#else
2030 EntrySize = 0;
2031 #endif*/
2032 if (EntrySize > EPL_SDO_MAX_PAYLOAD) { // segmented transfer
2033 pSdoComCon_p->m_SdoTransType = kEplSdoTransSegmented;
2034 // get pointer to object-entry data
2035 //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
2036 pSdoComCon_p->m_pData =
2037 EplObduGetObjectDataPtr(uiIndex, uiSubindex);
2038 //#endif
2039 } else { // expedited transfer
2040 pSdoComCon_p->m_SdoTransType = kEplSdoTransExpedited;
2043 pSdoComCon_p->m_uiTransSize = EntrySize;
2044 pSdoComCon_p->m_uiTransferredByte = 0;
2046 Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
2047 uiIndex,
2048 uiSubindex, kEplSdoComSendTypeRes);
2049 if (Ret != kEplSuccessful) {
2050 // error -> abort
2051 dwAbortCode = EPL_SDOAC_GENERAL_ERROR;
2052 // send abort
2053 pSdoComCon_p->m_pData = (BYTE *) & dwAbortCode;
2054 Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
2055 uiIndex,
2056 uiSubindex,
2057 kEplSdoComSendTypeAbort);
2058 goto Exit;
2061 Exit:
2062 return Ret;
2064 #endif
2066 //---------------------------------------------------------------------------
2068 // Function: EplSdoComServerSendFrameIntern();
2070 // Description: function creats and send a frame for server
2074 // Parameters: pSdoComCon_p = pointer to control structure of connection
2075 // uiIndex_p = index to send if expedited transfer else 0
2076 // uiSubIndex_p = subindex to send if expedited transfer else 0
2077 // SendType_p = to of frame to send
2079 // Returns: tEplKernel = errorcode
2082 // State:
2084 //---------------------------------------------------------------------------
2085 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
2086 static tEplKernel EplSdoComServerSendFrameIntern(tEplSdoComCon * pSdoComCon_p,
2087 unsigned int uiIndex_p,
2088 unsigned int uiSubIndex_p,
2089 tEplSdoComSendType SendType_p)
2091 tEplKernel Ret;
2092 BYTE abFrame[EPL_MAX_SDO_FRAME_SIZE];
2093 tEplFrame *pFrame;
2094 tEplAsySdoCom *pCommandFrame;
2095 unsigned int uiSizeOfFrame;
2096 BYTE bFlag;
2098 Ret = kEplSuccessful;
2100 pFrame = (tEplFrame *) & abFrame[0];
2102 EPL_MEMSET(&abFrame[0], 0x00, sizeof(abFrame));
2104 // build generic part of frame
2105 // get pointer to command layerpart of frame
2106 pCommandFrame =
2107 &pFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame.
2108 m_le_abSdoSeqPayload;
2109 AmiSetByteToLe(&pCommandFrame->m_le_bCommandId,
2110 pSdoComCon_p->m_SdoServiceType);
2111 AmiSetByteToLe(&pCommandFrame->m_le_bTransactionId,
2112 pSdoComCon_p->m_bTransactionId);
2114 // set size to header size
2115 uiSizeOfFrame = 8;
2117 // check SendType
2118 switch (SendType_p) {
2119 // requestframe to send
2120 case kEplSdoComSendTypeReq:
2122 // nothing to do for server
2123 //-> error
2124 Ret = kEplSdoComInvalidSendType;
2125 break;
2128 // response without data to send
2129 case kEplSdoComSendTypeAckRes:
2131 // set response flag
2132 AmiSetByteToLe(&pCommandFrame->m_le_bFlags, 0x80);
2134 // send frame
2135 Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl,
2136 uiSizeOfFrame, pFrame);
2138 break;
2141 // responsframe to send
2142 case kEplSdoComSendTypeRes:
2144 // set response flag
2145 bFlag = AmiGetByteFromLe(&pCommandFrame->m_le_bFlags);
2146 bFlag |= 0x80;
2147 AmiSetByteToLe(&pCommandFrame->m_le_bFlags, bFlag);
2149 // check type of resonse
2150 if (pSdoComCon_p->m_SdoTransType == kEplSdoTransExpedited) { // Expedited transfer
2151 // copy data in frame
2152 //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
2153 Ret = EplObduReadEntryToLe(uiIndex_p,
2154 uiSubIndex_p,
2155 &pCommandFrame->
2156 m_le_abCommandData
2157 [0],
2158 (tEplObdSize *) &
2159 pSdoComCon_p->
2160 m_uiTransSize);
2161 if (Ret != kEplSuccessful) {
2162 goto Exit;
2164 //#endif
2166 // set size of frame
2167 AmiSetWordToLe(&pCommandFrame->
2168 m_le_wSegmentSize,
2169 (WORD) pSdoComCon_p->
2170 m_uiTransSize);
2172 // correct byte-counter
2173 uiSizeOfFrame += pSdoComCon_p->m_uiTransSize;
2174 pSdoComCon_p->m_uiTransferredByte +=
2175 pSdoComCon_p->m_uiTransSize;
2176 pSdoComCon_p->m_uiTransSize = 0;
2178 // send frame
2179 uiSizeOfFrame += pSdoComCon_p->m_uiTransSize;
2180 Ret =
2181 EplSdoAsySeqSendData(pSdoComCon_p->
2182 m_SdoSeqConHdl,
2183 uiSizeOfFrame, pFrame);
2184 } else if (pSdoComCon_p->m_SdoTransType == kEplSdoTransSegmented) { // segmented transfer
2185 // distinguish between init, segment and complete
2186 if (pSdoComCon_p->m_uiTransferredByte == 0) { // init
2187 // set init flag
2188 bFlag =
2189 AmiGetByteFromLe(&pCommandFrame->
2190 m_le_bFlags);
2191 bFlag |= 0x10;
2192 AmiSetByteToLe(&pCommandFrame->
2193 m_le_bFlags, bFlag);
2194 // init variable header
2195 AmiSetDwordToLe(&pCommandFrame->
2196 m_le_abCommandData[0],
2197 pSdoComCon_p->
2198 m_uiTransSize);
2199 // copy data in frame
2200 EPL_MEMCPY(&pCommandFrame->
2201 m_le_abCommandData[4],
2202 pSdoComCon_p->m_pData,
2203 (EPL_SDO_MAX_PAYLOAD - 4));
2205 // correct byte-counter
2206 pSdoComCon_p->m_uiTransSize -=
2207 (EPL_SDO_MAX_PAYLOAD - 4);
2208 pSdoComCon_p->m_uiTransferredByte +=
2209 (EPL_SDO_MAX_PAYLOAD - 4);
2210 // move data pointer
2211 pSdoComCon_p->m_pData +=
2212 (EPL_SDO_MAX_PAYLOAD - 4);
2214 // set segment size
2215 AmiSetWordToLe(&pCommandFrame->
2216 m_le_wSegmentSize,
2217 (EPL_SDO_MAX_PAYLOAD -
2218 4));
2220 // send frame
2221 uiSizeOfFrame += EPL_SDO_MAX_PAYLOAD;
2222 Ret =
2223 EplSdoAsySeqSendData(pSdoComCon_p->
2224 m_SdoSeqConHdl,
2225 uiSizeOfFrame,
2226 pFrame);
2228 } else
2229 if ((pSdoComCon_p->m_uiTransferredByte > 0)
2230 && (pSdoComCon_p->m_uiTransSize > EPL_SDO_MAX_PAYLOAD)) { // segment
2231 // set segment flag
2232 bFlag =
2233 AmiGetByteFromLe(&pCommandFrame->
2234 m_le_bFlags);
2235 bFlag |= 0x20;
2236 AmiSetByteToLe(&pCommandFrame->
2237 m_le_bFlags, bFlag);
2239 // copy data in frame
2240 EPL_MEMCPY(&pCommandFrame->
2241 m_le_abCommandData[0],
2242 pSdoComCon_p->m_pData,
2243 EPL_SDO_MAX_PAYLOAD);
2245 // correct byte-counter
2246 pSdoComCon_p->m_uiTransSize -=
2247 EPL_SDO_MAX_PAYLOAD;
2248 pSdoComCon_p->m_uiTransferredByte +=
2249 EPL_SDO_MAX_PAYLOAD;
2250 // move data pointer
2251 pSdoComCon_p->m_pData +=
2252 EPL_SDO_MAX_PAYLOAD;
2254 // set segment size
2255 AmiSetWordToLe(&pCommandFrame->
2256 m_le_wSegmentSize,
2257 EPL_SDO_MAX_PAYLOAD);
2259 // send frame
2260 uiSizeOfFrame += EPL_SDO_MAX_PAYLOAD;
2261 Ret =
2262 EplSdoAsySeqSendData(pSdoComCon_p->
2263 m_SdoSeqConHdl,
2264 uiSizeOfFrame,
2265 pFrame);
2266 } else {
2267 if ((pSdoComCon_p->m_uiTransSize == 0)
2268 && (pSdoComCon_p->
2269 m_SdoServiceType !=
2270 kEplSdoServiceWriteByIndex)) {
2271 goto Exit;
2273 // complete
2274 // set segment complete flag
2275 bFlag =
2276 AmiGetByteFromLe(&pCommandFrame->
2277 m_le_bFlags);
2278 bFlag |= 0x30;
2279 AmiSetByteToLe(&pCommandFrame->
2280 m_le_bFlags, bFlag);
2282 // copy data in frame
2283 EPL_MEMCPY(&pCommandFrame->
2284 m_le_abCommandData[0],
2285 pSdoComCon_p->m_pData,
2286 pSdoComCon_p->m_uiTransSize);
2288 // correct byte-counter
2289 pSdoComCon_p->m_uiTransferredByte +=
2290 pSdoComCon_p->m_uiTransSize;
2292 // move data pointer
2293 pSdoComCon_p->m_pData +=
2294 pSdoComCon_p->m_uiTransSize;
2296 // set segment size
2297 AmiSetWordToLe(&pCommandFrame->
2298 m_le_wSegmentSize,
2299 (WORD) pSdoComCon_p->
2300 m_uiTransSize);
2302 // send frame
2303 uiSizeOfFrame +=
2304 pSdoComCon_p->m_uiTransSize;
2305 pSdoComCon_p->m_uiTransSize = 0;
2306 Ret =
2307 EplSdoAsySeqSendData(pSdoComCon_p->
2308 m_SdoSeqConHdl,
2309 uiSizeOfFrame,
2310 pFrame);
2314 break;
2316 // abort to send
2317 case kEplSdoComSendTypeAbort:
2319 // set response and abort flag
2320 bFlag = AmiGetByteFromLe(&pCommandFrame->m_le_bFlags);
2321 bFlag |= 0xC0;
2322 AmiSetByteToLe(&pCommandFrame->m_le_bFlags, bFlag);
2324 // copy abortcode to frame
2325 AmiSetDwordToLe(&pCommandFrame->m_le_abCommandData[0],
2326 *((DWORD *) pSdoComCon_p->m_pData));
2328 // set size of segment
2329 AmiSetWordToLe(&pCommandFrame->m_le_wSegmentSize,
2330 sizeof(DWORD));
2332 // update counter
2333 pSdoComCon_p->m_uiTransferredByte = sizeof(DWORD);
2334 pSdoComCon_p->m_uiTransSize = 0;
2336 // calc framesize
2337 uiSizeOfFrame += sizeof(DWORD);
2338 Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl,
2339 uiSizeOfFrame, pFrame);
2340 break;
2342 } // end of switch(SendType_p)
2344 Exit:
2345 return Ret;
2347 #endif
2348 //---------------------------------------------------------------------------
2350 // Function: EplSdoComServerInitWriteByIndex
2352 // Description: function start the processing of an write by index command
2356 // Parameters: pSdoComCon_p = pointer to control structure of connection
2357 // pAsySdoCom_p = pointer to received frame
2359 // Returns: tEplKernel = errorcode
2362 // State:
2364 //---------------------------------------------------------------------------
2365 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
2366 static tEplKernel EplSdoComServerInitWriteByIndex(tEplSdoComCon * pSdoComCon_p,
2367 tEplAsySdoCom * pAsySdoCom_p)
2369 tEplKernel Ret = kEplSuccessful;
2370 unsigned int uiIndex;
2371 unsigned int uiSubindex;
2372 unsigned int uiBytesToTransfer;
2373 tEplObdSize EntrySize;
2374 tEplObdAccess AccessType;
2375 DWORD dwAbortCode;
2376 BYTE *pbSrcData;
2378 dwAbortCode = 0;
2380 // a init of a write
2381 // -> variable part of header possible
2383 // check if expedited or segmented transfer
2384 if ((pAsySdoCom_p->m_le_bFlags & 0x30) == 0x10) { // initiate segmented transfer
2385 pSdoComCon_p->m_SdoTransType = kEplSdoTransSegmented;
2386 // get index and subindex
2387 uiIndex =
2388 AmiGetWordFromLe(&pAsySdoCom_p->m_le_abCommandData[4]);
2389 uiSubindex =
2390 AmiGetByteFromLe(&pAsySdoCom_p->m_le_abCommandData[6]);
2391 // get source-pointer for copy
2392 pbSrcData = &pAsySdoCom_p->m_le_abCommandData[8];
2393 // save size
2394 pSdoComCon_p->m_uiTransSize =
2395 AmiGetDwordFromLe(&pAsySdoCom_p->m_le_abCommandData[0]);
2397 } else if ((pAsySdoCom_p->m_le_bFlags & 0x30) == 0x00) { // expedited transfer
2398 pSdoComCon_p->m_SdoTransType = kEplSdoTransExpedited;
2399 // get index and subindex
2400 uiIndex =
2401 AmiGetWordFromLe(&pAsySdoCom_p->m_le_abCommandData[0]);
2402 uiSubindex =
2403 AmiGetByteFromLe(&pAsySdoCom_p->m_le_abCommandData[2]);
2404 // get source-pointer for copy
2405 pbSrcData = &pAsySdoCom_p->m_le_abCommandData[4];
2406 // save size
2407 pSdoComCon_p->m_uiTransSize =
2408 AmiGetWordFromLe(&pAsySdoCom_p->m_le_wSegmentSize);
2409 // subtract header
2410 pSdoComCon_p->m_uiTransSize -= 4;
2412 } else {
2413 // just ignore any other transfer type
2414 goto Exit;
2417 // check accesstype of entry
2418 // existens of entry
2419 //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
2420 Ret = EplObduGetAccessType(uiIndex, uiSubindex, &AccessType);
2421 /*#else
2422 Ret = kEplObdSubindexNotExist;
2423 AccessType = 0;
2424 #endif*/
2425 if (Ret == kEplObdSubindexNotExist) { // subentry doesn't exist
2426 pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_SUB_INDEX_NOT_EXIST;
2427 // send abort
2428 // d.k. This is wrong: k.t. not needed send abort on end of write
2429 /*pSdoComCon_p->m_pData = (BYTE*)pSdoComCon_p->m_dwLastAbortCode;
2430 Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
2431 uiIndex,
2432 uiSubindex,
2433 kEplSdoComSendTypeAbort); */
2434 goto Abort;
2435 } else if (Ret != kEplSuccessful) { // entry doesn't exist
2436 pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_OBJECT_NOT_EXIST;
2437 // send abort
2438 // d.k. This is wrong: k.t. not needed send abort on end of write
2440 pSdoComCon_p->m_pData = (BYTE*)&dwAbortCode;
2441 Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
2442 uiIndex,
2443 uiSubindex,
2444 kEplSdoComSendTypeAbort); */
2445 goto Abort;
2447 // compare accesstype must be read
2448 if ((AccessType & kEplObdAccWrite) == 0) {
2450 if ((AccessType & kEplObdAccRead) != 0) {
2451 // entry write a read only object
2452 pSdoComCon_p->m_dwLastAbortCode =
2453 EPL_SDOAC_WRITE_TO_READ_ONLY_OBJ;
2454 } else {
2455 pSdoComCon_p->m_dwLastAbortCode =
2456 EPL_SDOAC_UNSUPPORTED_ACCESS;
2458 // send abort
2459 // d.k. This is wrong: k.t. not needed send abort on end of write
2460 /*pSdoComCon_p->m_pData = (BYTE*)&dwAbortCode;
2461 Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
2462 uiIndex,
2463 uiSubindex,
2464 kEplSdoComSendTypeAbort); */
2465 goto Abort;
2467 // save service
2468 pSdoComCon_p->m_SdoServiceType = kEplSdoServiceWriteByIndex;
2470 pSdoComCon_p->m_uiTransferredByte = 0;
2472 // write data to OD
2473 if (pSdoComCon_p->m_SdoTransType == kEplSdoTransExpedited) { // expedited transfer
2474 // size checking is done by EplObduWriteEntryFromLe()
2476 //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
2477 Ret = EplObduWriteEntryFromLe(uiIndex,
2478 uiSubindex,
2479 pbSrcData,
2480 pSdoComCon_p->m_uiTransSize);
2481 switch (Ret) {
2482 case kEplSuccessful:
2484 break;
2487 case kEplObdAccessViolation:
2489 pSdoComCon_p->m_dwLastAbortCode =
2490 EPL_SDOAC_UNSUPPORTED_ACCESS;
2491 // send abort
2492 goto Abort;
2495 case kEplObdValueLengthError:
2497 pSdoComCon_p->m_dwLastAbortCode =
2498 EPL_SDOAC_DATA_TYPE_LENGTH_NOT_MATCH;
2499 // send abort
2500 goto Abort;
2503 case kEplObdValueTooHigh:
2505 pSdoComCon_p->m_dwLastAbortCode =
2506 EPL_SDOAC_VALUE_RANGE_TOO_HIGH;
2507 // send abort
2508 goto Abort;
2511 case kEplObdValueTooLow:
2513 pSdoComCon_p->m_dwLastAbortCode =
2514 EPL_SDOAC_VALUE_RANGE_TOO_LOW;
2515 // send abort
2516 goto Abort;
2519 default:
2521 pSdoComCon_p->m_dwLastAbortCode =
2522 EPL_SDOAC_GENERAL_ERROR;
2523 // send abort
2524 goto Abort;
2527 //#endif
2528 // send command acknowledge
2529 Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
2532 kEplSdoComSendTypeAckRes);
2534 pSdoComCon_p->m_uiTransSize = 0;
2535 goto Exit;
2536 } else {
2537 // get size of the object to check if it fits
2538 // because we directly write to the destination memory
2539 // d.k. no one calls the user OD callback function
2541 //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
2542 EntrySize = EplObduGetDataSize(uiIndex, uiSubindex);
2543 /*#else
2544 EntrySize = 0;
2545 #endif */
2546 if (EntrySize < pSdoComCon_p->m_uiTransSize) { // parameter too big
2547 pSdoComCon_p->m_dwLastAbortCode =
2548 EPL_SDOAC_DATA_TYPE_LENGTH_TOO_HIGH;
2549 // send abort
2550 // d.k. This is wrong: k.t. not needed send abort on end of write
2551 /*pSdoComCon_p->m_pData = (BYTE*)&dwAbortCode;
2552 Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
2553 uiIndex,
2554 uiSubindex,
2555 kEplSdoComSendTypeAbort); */
2556 goto Abort;
2559 uiBytesToTransfer =
2560 AmiGetWordFromLe(&pAsySdoCom_p->m_le_wSegmentSize);
2561 // eleminate header (Command header (8) + variable part (4) + Command header (4))
2562 uiBytesToTransfer -= 16;
2563 // get pointer to object entry
2564 //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
2565 pSdoComCon_p->m_pData = EplObduGetObjectDataPtr(uiIndex,
2566 uiSubindex);
2567 //#endif
2568 if (pSdoComCon_p->m_pData == NULL) {
2569 pSdoComCon_p->m_dwLastAbortCode =
2570 EPL_SDOAC_GENERAL_ERROR;
2571 // send abort
2572 // d.k. This is wrong: k.t. not needed send abort on end of write
2573 /* pSdoComCon_p->m_pData = (BYTE*)&pSdoComCon_p->m_dwLastAbortCode;
2574 Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
2575 uiIndex,
2576 uiSubindex,
2577 kEplSdoComSendTypeAbort);*/
2578 goto Abort;
2580 // copy data
2581 EPL_MEMCPY(pSdoComCon_p->m_pData, pbSrcData, uiBytesToTransfer);
2583 // update internal counter
2584 pSdoComCon_p->m_uiTransferredByte = uiBytesToTransfer;
2585 pSdoComCon_p->m_uiTransSize -= uiBytesToTransfer;
2587 // update target pointer
2588 ( /*(BYTE*) */ pSdoComCon_p->m_pData) += uiBytesToTransfer;
2590 // send acknowledge without any Command layer data
2591 Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl,
2592 0, (tEplFrame *) NULL);
2593 goto Exit;
2596 Abort:
2597 if (pSdoComCon_p->m_dwLastAbortCode != 0) {
2598 // send abort
2599 pSdoComCon_p->m_pData =
2600 (BYTE *) & pSdoComCon_p->m_dwLastAbortCode;
2601 Ret =
2602 EplSdoComServerSendFrameIntern(pSdoComCon_p, uiIndex,
2603 uiSubindex,
2604 kEplSdoComSendTypeAbort);
2606 // reset abort code
2607 pSdoComCon_p->m_dwLastAbortCode = 0;
2608 pSdoComCon_p->m_uiTransSize = 0;
2609 goto Exit;
2612 Exit:
2613 return Ret;
2615 #endif
2617 //---------------------------------------------------------------------------
2619 // Function: EplSdoComClientSend
2621 // Description: function starts an sdo transfer an send all further frames
2625 // Parameters: pSdoComCon_p = pointer to control structure of connection
2627 // Returns: tEplKernel = errorcode
2630 // State:
2632 //---------------------------------------------------------------------------
2633 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
2634 static tEplKernel EplSdoComClientSend(tEplSdoComCon * pSdoComCon_p)
2636 tEplKernel Ret;
2637 BYTE abFrame[EPL_MAX_SDO_FRAME_SIZE];
2638 tEplFrame *pFrame;
2639 tEplAsySdoCom *pCommandFrame;
2640 unsigned int uiSizeOfFrame;
2641 BYTE bFlags;
2642 BYTE *pbPayload;
2644 Ret = kEplSuccessful;
2646 pFrame = (tEplFrame *) & abFrame[0];
2648 EPL_MEMSET(&abFrame[0], 0x00, sizeof(abFrame));
2650 // build generic part of frame
2651 // get pointer to command layerpart of frame
2652 pCommandFrame =
2653 &pFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame.
2654 m_le_abSdoSeqPayload;
2655 AmiSetByteToLe(&pCommandFrame->m_le_bCommandId,
2656 pSdoComCon_p->m_SdoServiceType);
2657 AmiSetByteToLe(&pCommandFrame->m_le_bTransactionId,
2658 pSdoComCon_p->m_bTransactionId);
2660 // set size constant part of header
2661 uiSizeOfFrame = 8;
2663 // check if first frame to send -> command header needed
2664 if (pSdoComCon_p->m_uiTransSize > 0) {
2665 if (pSdoComCon_p->m_uiTransferredByte == 0) { // start SDO transfer
2666 // check if segmented or expedited transfer
2667 // only for write commands
2668 switch (pSdoComCon_p->m_SdoServiceType) {
2669 case kEplSdoServiceReadByIndex:
2670 { // first frame of read access always expedited
2671 pSdoComCon_p->m_SdoTransType =
2672 kEplSdoTransExpedited;
2673 pbPayload =
2674 &pCommandFrame->
2675 m_le_abCommandData[0];
2676 // fill rest of header
2677 AmiSetWordToLe(&pCommandFrame->
2678 m_le_wSegmentSize, 4);
2680 // create command header
2681 AmiSetWordToLe(pbPayload,
2682 (WORD) pSdoComCon_p->
2683 m_uiTargetIndex);
2684 pbPayload += 2;
2685 AmiSetByteToLe(pbPayload,
2686 (BYTE) pSdoComCon_p->
2687 m_uiTargetSubIndex);
2688 // calc size
2689 uiSizeOfFrame += 4;
2691 // set pSdoComCon_p->m_uiTransferredByte to one
2692 pSdoComCon_p->m_uiTransferredByte = 1;
2693 break;
2696 case kEplSdoServiceWriteByIndex:
2698 if (pSdoComCon_p->m_uiTransSize > EPL_SDO_MAX_PAYLOAD) { // segmented transfer
2699 // -> variable part of header needed
2700 // save that transfer is segmented
2701 pSdoComCon_p->m_SdoTransType =
2702 kEplSdoTransSegmented;
2703 // fill variable part of header
2704 AmiSetDwordToLe(&pCommandFrame->
2705 m_le_abCommandData
2706 [0],
2707 pSdoComCon_p->
2708 m_uiTransSize);
2709 // set pointer to real payload
2710 pbPayload =
2711 &pCommandFrame->
2712 m_le_abCommandData[4];
2713 // fill rest of header
2714 AmiSetWordToLe(&pCommandFrame->
2715 m_le_wSegmentSize,
2716 EPL_SDO_MAX_PAYLOAD);
2717 bFlags = 0x10;
2718 AmiSetByteToLe(&pCommandFrame->
2719 m_le_bFlags,
2720 bFlags);
2721 // create command header
2722 AmiSetWordToLe(pbPayload,
2723 (WORD)
2724 pSdoComCon_p->
2725 m_uiTargetIndex);
2726 pbPayload += 2;
2727 AmiSetByteToLe(pbPayload,
2728 (BYTE)
2729 pSdoComCon_p->
2730 m_uiTargetSubIndex);
2731 // on byte for reserved
2732 pbPayload += 2;
2733 // calc size
2734 uiSizeOfFrame +=
2735 EPL_SDO_MAX_PAYLOAD;
2737 // copy payload
2738 EPL_MEMCPY(pbPayload,
2739 pSdoComCon_p->
2740 m_pData,
2741 (EPL_SDO_MAX_PAYLOAD
2742 - 8));
2743 pSdoComCon_p->m_pData +=
2744 (EPL_SDO_MAX_PAYLOAD - 8);
2745 // correct intern counter
2746 pSdoComCon_p->m_uiTransSize -=
2747 (EPL_SDO_MAX_PAYLOAD - 8);
2748 pSdoComCon_p->
2749 m_uiTransferredByte =
2750 (EPL_SDO_MAX_PAYLOAD - 8);
2752 } else { // expedited trandsfer
2753 // save that transfer is expedited
2754 pSdoComCon_p->m_SdoTransType =
2755 kEplSdoTransExpedited;
2756 pbPayload =
2757 &pCommandFrame->
2758 m_le_abCommandData[0];
2760 // create command header
2761 AmiSetWordToLe(pbPayload,
2762 (WORD)
2763 pSdoComCon_p->
2764 m_uiTargetIndex);
2765 pbPayload += 2;
2766 AmiSetByteToLe(pbPayload,
2767 (BYTE)
2768 pSdoComCon_p->
2769 m_uiTargetSubIndex);
2770 // + 2 -> one byte for subindex and one byte reserved
2771 pbPayload += 2;
2772 // copy data
2773 EPL_MEMCPY(pbPayload,
2774 pSdoComCon_p->
2775 m_pData,
2776 pSdoComCon_p->
2777 m_uiTransSize);
2778 // calc size
2779 uiSizeOfFrame +=
2780 (4 +
2781 pSdoComCon_p->
2782 m_uiTransSize);
2783 // fill rest of header
2784 AmiSetWordToLe(&pCommandFrame->
2785 m_le_wSegmentSize,
2786 (WORD) (4 +
2787 pSdoComCon_p->
2788 m_uiTransSize));
2790 pSdoComCon_p->
2791 m_uiTransferredByte =
2792 pSdoComCon_p->m_uiTransSize;
2793 pSdoComCon_p->m_uiTransSize = 0;
2795 break;
2798 case kEplSdoServiceNIL:
2799 default:
2800 // invalid service requested
2801 Ret = kEplSdoComInvalidServiceType;
2802 goto Exit;
2803 } // end of switch(pSdoComCon_p->m_SdoServiceType)
2804 } else // (pSdoComCon_p->m_uiTransferredByte > 0)
2805 { // continue SDO transfer
2806 switch (pSdoComCon_p->m_SdoServiceType) {
2807 // for expedited read is nothing to do
2808 // -> server sends data
2810 case kEplSdoServiceWriteByIndex:
2811 { // send next frame
2812 if (pSdoComCon_p->m_SdoTransType ==
2813 kEplSdoTransSegmented) {
2814 if (pSdoComCon_p->m_uiTransSize > EPL_SDO_MAX_PAYLOAD) { // next segment
2815 pbPayload =
2816 &pCommandFrame->
2817 m_le_abCommandData
2818 [0];
2819 // fill rest of header
2820 AmiSetWordToLe
2821 (&pCommandFrame->
2822 m_le_wSegmentSize,
2823 EPL_SDO_MAX_PAYLOAD);
2824 bFlags = 0x20;
2825 AmiSetByteToLe
2826 (&pCommandFrame->
2827 m_le_bFlags,
2828 bFlags);
2829 // copy data
2830 EPL_MEMCPY(pbPayload,
2831 pSdoComCon_p->
2832 m_pData,
2833 EPL_SDO_MAX_PAYLOAD);
2834 pSdoComCon_p->m_pData +=
2835 EPL_SDO_MAX_PAYLOAD;
2836 // correct intern counter
2837 pSdoComCon_p->
2838 m_uiTransSize -=
2839 EPL_SDO_MAX_PAYLOAD;
2840 pSdoComCon_p->
2841 m_uiTransferredByte
2843 EPL_SDO_MAX_PAYLOAD;
2844 // calc size
2845 uiSizeOfFrame +=
2846 EPL_SDO_MAX_PAYLOAD;
2848 } else { // end of transfer
2849 pbPayload =
2850 &pCommandFrame->
2851 m_le_abCommandData
2852 [0];
2853 // fill rest of header
2854 AmiSetWordToLe
2855 (&pCommandFrame->
2856 m_le_wSegmentSize,
2857 (WORD)
2858 pSdoComCon_p->
2859 m_uiTransSize);
2860 bFlags = 0x30;
2861 AmiSetByteToLe
2862 (&pCommandFrame->
2863 m_le_bFlags,
2864 bFlags);
2865 // copy data
2866 EPL_MEMCPY(pbPayload,
2867 pSdoComCon_p->
2868 m_pData,
2869 pSdoComCon_p->
2870 m_uiTransSize);
2871 pSdoComCon_p->m_pData +=
2872 pSdoComCon_p->
2873 m_uiTransSize;
2874 // calc size
2875 uiSizeOfFrame +=
2876 pSdoComCon_p->
2877 m_uiTransSize;
2878 // correct intern counter
2879 pSdoComCon_p->
2880 m_uiTransSize = 0;
2881 pSdoComCon_p->
2882 m_uiTransferredByte
2884 pSdoComCon_p->
2885 m_uiTransSize;
2888 } else {
2889 goto Exit;
2891 break;
2893 default:
2895 goto Exit;
2897 } // end of switch(pSdoComCon_p->m_SdoServiceType)
2899 } else {
2900 goto Exit;
2903 // call send function of lower layer
2904 switch (pSdoComCon_p->m_SdoProtType) {
2905 case kEplSdoTypeAsnd:
2906 case kEplSdoTypeUdp:
2908 Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl,
2909 uiSizeOfFrame, pFrame);
2910 break;
2913 default:
2915 Ret = kEplSdoComUnsupportedProt;
2917 } // end of switch(pSdoComCon_p->m_SdoProtType)
2919 Exit:
2920 return Ret;
2923 #endif
2924 //---------------------------------------------------------------------------
2926 // Function: EplSdoComClientProcessFrame
2928 // Description: function process a received frame
2932 // Parameters: SdoComCon_p = connection handle
2933 // pAsySdoCom_p = pointer to frame to process
2935 // Returns: tEplKernel = errorcode
2938 // State:
2940 //---------------------------------------------------------------------------
2941 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
2942 static tEplKernel EplSdoComClientProcessFrame(tEplSdoComConHdl SdoComCon_p,
2943 tEplAsySdoCom * pAsySdoCom_p)
2945 tEplKernel Ret;
2946 BYTE bBuffer;
2947 unsigned int uiBuffer;
2948 unsigned int uiDataSize;
2949 unsigned long ulBuffer;
2950 tEplSdoComCon *pSdoComCon;
2952 Ret = kEplSuccessful;
2954 // get pointer to control structure
2955 pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComCon_p];
2957 // check if transaction Id fit
2958 bBuffer = AmiGetByteFromLe(&pAsySdoCom_p->m_le_bTransactionId);
2959 if (pSdoComCon->m_bTransactionId != bBuffer) {
2960 // incorrect transaction id
2962 // if running transfer
2963 if ((pSdoComCon->m_uiTransferredByte != 0)
2964 && (pSdoComCon->m_uiTransSize != 0)) {
2965 pSdoComCon->m_dwLastAbortCode = EPL_SDOAC_GENERAL_ERROR;
2966 // -> send abort
2967 EplSdoComClientSendAbort(pSdoComCon,
2968 pSdoComCon->m_dwLastAbortCode);
2969 // call callback of application
2970 Ret =
2971 EplSdoComTransferFinished(SdoComCon_p, pSdoComCon,
2972 kEplSdoComTransferTxAborted);
2975 } else { // check if correct command
2976 bBuffer = AmiGetByteFromLe(&pAsySdoCom_p->m_le_bCommandId);
2977 if (pSdoComCon->m_SdoServiceType != bBuffer) {
2978 // incorrect command
2979 // if running transfer
2980 if ((pSdoComCon->m_uiTransferredByte != 0)
2981 && (pSdoComCon->m_uiTransSize != 0)) {
2982 pSdoComCon->m_dwLastAbortCode =
2983 EPL_SDOAC_GENERAL_ERROR;
2984 // -> send abort
2985 EplSdoComClientSendAbort(pSdoComCon,
2986 pSdoComCon->
2987 m_dwLastAbortCode);
2988 // call callback of application
2989 Ret =
2990 EplSdoComTransferFinished(SdoComCon_p,
2991 pSdoComCon,
2992 kEplSdoComTransferTxAborted);
2995 } else { // switch on command
2996 switch (pSdoComCon->m_SdoServiceType) {
2997 case kEplSdoServiceWriteByIndex:
2998 { // check if confirmation from server
2999 // nothing more to do
3000 break;
3003 case kEplSdoServiceReadByIndex:
3004 { // check if it is an segmented or an expedited transfer
3005 bBuffer =
3006 AmiGetByteFromLe(&pAsySdoCom_p->
3007 m_le_bFlags);
3008 // mask uninteressting bits
3009 bBuffer &= 0x30;
3010 switch (bBuffer) {
3011 // expedited transfer
3012 case 0x00:
3014 // check size of buffer
3015 uiBuffer =
3016 AmiGetWordFromLe
3017 (&pAsySdoCom_p->
3018 m_le_wSegmentSize);
3019 if (uiBuffer > pSdoComCon->m_uiTransSize) { // buffer provided by the application is to small
3020 // copy only a part
3021 uiDataSize =
3022 pSdoComCon->
3023 m_uiTransSize;
3024 } else { // buffer fits
3025 uiDataSize =
3026 uiBuffer;
3029 // copy data
3030 EPL_MEMCPY(pSdoComCon->
3031 m_pData,
3032 &pAsySdoCom_p->
3033 m_le_abCommandData
3034 [0],
3035 uiDataSize);
3037 // correct counter
3038 pSdoComCon->
3039 m_uiTransSize = 0;
3040 pSdoComCon->
3041 m_uiTransferredByte
3042 = uiDataSize;
3043 break;
3046 // start of a segmented transfer
3047 case 0x10:
3048 { // get total size of transfer
3049 ulBuffer =
3050 AmiGetDwordFromLe
3051 (&pAsySdoCom_p->
3052 m_le_abCommandData
3053 [0]);
3054 if (ulBuffer <= pSdoComCon->m_uiTransSize) { // buffer fit
3055 pSdoComCon->
3056 m_uiTransSize
3058 (unsigned
3059 int)
3060 ulBuffer;
3061 } else { // buffer to small
3062 // send abort
3063 pSdoComCon->
3064 m_dwLastAbortCode
3066 EPL_SDOAC_DATA_TYPE_LENGTH_TOO_HIGH;
3067 // -> send abort
3068 EplSdoComClientSendAbort
3069 (pSdoComCon,
3070 pSdoComCon->
3071 m_dwLastAbortCode);
3072 // call callback of application
3073 Ret =
3074 EplSdoComTransferFinished
3075 (SdoComCon_p,
3076 pSdoComCon,
3077 kEplSdoComTransferRxAborted);
3078 goto Exit;
3081 // get segment size
3082 // check size of buffer
3083 uiBuffer =
3084 AmiGetWordFromLe
3085 (&pAsySdoCom_p->
3086 m_le_wSegmentSize);
3087 // subtract size of vaiable header from datasize
3088 uiBuffer -= 4;
3089 // copy data
3090 EPL_MEMCPY(pSdoComCon->
3091 m_pData,
3092 &pAsySdoCom_p->
3093 m_le_abCommandData
3094 [4],
3095 uiBuffer);
3097 // correct counter an pointer
3098 pSdoComCon->m_pData +=
3099 uiBuffer;
3100 pSdoComCon->
3101 m_uiTransferredByte
3102 += uiBuffer;
3103 pSdoComCon->
3104 m_uiTransSize -=
3105 uiBuffer;
3107 break;
3110 // segment
3111 case 0x20:
3113 // get segment size
3114 // check size of buffer
3115 uiBuffer =
3116 AmiGetWordFromLe
3117 (&pAsySdoCom_p->
3118 m_le_wSegmentSize);
3119 // check if data to copy fit to buffer
3120 if (uiBuffer >= pSdoComCon->m_uiTransSize) { // to much data
3121 uiBuffer =
3122 (pSdoComCon->
3123 m_uiTransSize
3124 - 1);
3126 // copy data
3127 EPL_MEMCPY(pSdoComCon->
3128 m_pData,
3129 &pAsySdoCom_p->
3130 m_le_abCommandData
3131 [0],
3132 uiBuffer);
3134 // correct counter an pointer
3135 pSdoComCon->m_pData +=
3136 uiBuffer;
3137 pSdoComCon->
3138 m_uiTransferredByte
3139 += uiBuffer;
3140 pSdoComCon->
3141 m_uiTransSize -=
3142 uiBuffer;
3143 break;
3146 // last segment
3147 case 0x30:
3149 // get segment size
3150 // check size of buffer
3151 uiBuffer =
3152 AmiGetWordFromLe
3153 (&pAsySdoCom_p->
3154 m_le_wSegmentSize);
3155 // check if data to copy fit to buffer
3156 if (uiBuffer > pSdoComCon->m_uiTransSize) { // to much data
3157 uiBuffer =
3158 (pSdoComCon->
3159 m_uiTransSize
3160 - 1);
3162 // copy data
3163 EPL_MEMCPY(pSdoComCon->
3164 m_pData,
3165 &pAsySdoCom_p->
3166 m_le_abCommandData
3167 [0],
3168 uiBuffer);
3170 // correct counter an pointer
3171 pSdoComCon->m_pData +=
3172 uiBuffer;
3173 pSdoComCon->
3174 m_uiTransferredByte
3175 += uiBuffer;
3176 pSdoComCon->
3177 m_uiTransSize = 0;
3179 break;
3181 } // end of switch(bBuffer & 0x30)
3183 break;
3186 case kEplSdoServiceNIL:
3187 default:
3188 // invalid service requested
3189 // $$$ d.k. What should we do?
3190 break;
3191 } // end of switch(pSdoComCon->m_SdoServiceType)
3195 Exit:
3196 return Ret;
3198 #endif
3200 //---------------------------------------------------------------------------
3202 // Function: EplSdoComClientSendAbort
3204 // Description: function send a abort message
3208 // Parameters: pSdoComCon_p = pointer to control structure of connection
3209 // dwAbortCode_p = Sdo abort code
3211 // Returns: tEplKernel = errorcode
3214 // State:
3216 //---------------------------------------------------------------------------
3217 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
3218 static tEplKernel EplSdoComClientSendAbort(tEplSdoComCon * pSdoComCon_p,
3219 DWORD dwAbortCode_p)
3221 tEplKernel Ret;
3222 BYTE abFrame[EPL_MAX_SDO_FRAME_SIZE];
3223 tEplFrame *pFrame;
3224 tEplAsySdoCom *pCommandFrame;
3225 unsigned int uiSizeOfFrame;
3227 Ret = kEplSuccessful;
3229 pFrame = (tEplFrame *) & abFrame[0];
3231 EPL_MEMSET(&abFrame[0], 0x00, sizeof(abFrame));
3233 // build generic part of frame
3234 // get pointer to command layerpart of frame
3235 pCommandFrame =
3236 &pFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame.
3237 m_le_abSdoSeqPayload;
3238 AmiSetByteToLe(&pCommandFrame->m_le_bCommandId,
3239 pSdoComCon_p->m_SdoServiceType);
3240 AmiSetByteToLe(&pCommandFrame->m_le_bTransactionId,
3241 pSdoComCon_p->m_bTransactionId);
3243 uiSizeOfFrame = 8;
3245 // set response and abort flag
3246 pCommandFrame->m_le_bFlags |= 0x40;
3248 // copy abortcode to frame
3249 AmiSetDwordToLe(&pCommandFrame->m_le_abCommandData[0], dwAbortCode_p);
3251 // set size of segment
3252 AmiSetWordToLe(&pCommandFrame->m_le_wSegmentSize, sizeof(DWORD));
3254 // update counter
3255 pSdoComCon_p->m_uiTransferredByte = sizeof(DWORD);
3256 pSdoComCon_p->m_uiTransSize = 0;
3258 // calc framesize
3259 uiSizeOfFrame += sizeof(DWORD);
3261 // save abort code
3262 pSdoComCon_p->m_dwLastAbortCode = dwAbortCode_p;
3264 // call send function of lower layer
3265 switch (pSdoComCon_p->m_SdoProtType) {
3266 case kEplSdoTypeAsnd:
3267 case kEplSdoTypeUdp:
3269 Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl,
3270 uiSizeOfFrame, pFrame);
3271 break;
3274 default:
3276 Ret = kEplSdoComUnsupportedProt;
3278 } // end of switch(pSdoComCon_p->m_SdoProtType)
3280 return Ret;
3282 #endif
3284 //---------------------------------------------------------------------------
3286 // Function: EplSdoComTransferFinished
3288 // Description: calls callback function of application if available
3289 // and clears entry in control structure
3291 // Parameters: pSdoComCon_p = pointer to control structure of connection
3292 // SdoComConState_p = state of SDO transfer
3294 // Returns: tEplKernel = errorcode
3297 // State:
3299 //---------------------------------------------------------------------------
3300 static tEplKernel EplSdoComTransferFinished(tEplSdoComConHdl SdoComCon_p,
3301 tEplSdoComCon * pSdoComCon_p,
3302 tEplSdoComConState SdoComConState_p)
3304 tEplKernel Ret;
3306 Ret = kEplSuccessful;
3308 if (pSdoComCon_p->m_pfnTransferFinished != NULL) {
3309 tEplSdoFinishedCb pfnTransferFinished;
3310 tEplSdoComFinished SdoComFinished;
3312 SdoComFinished.m_pUserArg = pSdoComCon_p->m_pUserArg;
3313 SdoComFinished.m_uiNodeId = pSdoComCon_p->m_uiNodeId;
3314 SdoComFinished.m_uiTargetIndex = pSdoComCon_p->m_uiTargetIndex;
3315 SdoComFinished.m_uiTargetSubIndex =
3316 pSdoComCon_p->m_uiTargetSubIndex;
3317 SdoComFinished.m_uiTransferredByte =
3318 pSdoComCon_p->m_uiTransferredByte;
3319 SdoComFinished.m_dwAbortCode = pSdoComCon_p->m_dwLastAbortCode;
3320 SdoComFinished.m_SdoComConHdl = SdoComCon_p;
3321 SdoComFinished.m_SdoComConState = SdoComConState_p;
3322 if (pSdoComCon_p->m_SdoServiceType ==
3323 kEplSdoServiceWriteByIndex) {
3324 SdoComFinished.m_SdoAccessType = kEplSdoAccessTypeWrite;
3325 } else {
3326 SdoComFinished.m_SdoAccessType = kEplSdoAccessTypeRead;
3329 // reset transfer state so this handle is not busy anymore
3330 pSdoComCon_p->m_uiTransferredByte = 0;
3331 pSdoComCon_p->m_uiTransSize = 0;
3333 pfnTransferFinished = pSdoComCon_p->m_pfnTransferFinished;
3334 // delete function pointer to inform application only once for each transfer
3335 pSdoComCon_p->m_pfnTransferFinished = NULL;
3337 // call application's callback function
3338 pfnTransferFinished(&SdoComFinished);
3342 return Ret;
3345 // EOF