Staging: add epl stack
[firefly-linux-kernel-4.4.55.git] / drivers / staging / epl / EplSdoComu.c
1 /****************************************************************************
2
3   (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4       www.systec-electronic.com
5
6   Project:      openPOWERLINK
7
8   Description:  source file for SDO Command Layer module
9
10   License:
11
12     Redistribution and use in source and binary forms, with or without
13     modification, are permitted provided that the following conditions
14     are met:
15
16     1. Redistributions of source code must retain the above copyright
17        notice, this list of conditions and the following disclaimer.
18
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.
22
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.
27
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.
40
41     Severability Clause:
42
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.
49
50   -------------------------------------------------------------------------
51
52                 $RCSfile: EplSdoComu.c,v $
53
54                 $Author: D.Krueger $
55
56                 $Revision: 1.14 $  $Date: 2008/10/17 15:32:32 $
57
58                 $State: Exp $
59
60                 Build Environment:
61                     GCC V3.4
62
63   -------------------------------------------------------------------------
64
65   Revision History:
66
67   2006/06/26 k.t.:   start of the implementation
68
69 ****************************************************************************/
70
71 #include "user/EplSdoComu.h"
72
73 #if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) == 0) &&\
74      (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) == 0)   )
75
76     #error 'ERROR: At least SDO Server or SDO Client should be activate!'
77
78 #endif
79
80 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
81     #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) == 0) && (EPL_OBD_USE_KERNEL == FALSE)
82
83     #error 'ERROR: SDO Server needs OBDu module!'
84
85     #endif
86
87 #endif
88
89 /***************************************************************************/
90 /*                                                                         */
91 /*                                                                         */
92 /*          G L O B A L   D E F I N I T I O N S                            */
93 /*                                                                         */
94 /*                                                                         */
95 /***************************************************************************/
96
97 //---------------------------------------------------------------------------
98 // const defines
99 //---------------------------------------------------------------------------
100
101 #ifndef EPL_MAX_SDO_COM_CON
102 #define EPL_MAX_SDO_COM_CON         5
103 #endif
104
105
106 //---------------------------------------------------------------------------
107 // local types
108 //---------------------------------------------------------------------------
109
110 // intern events
111 typedef enum
112 {
113     kEplSdoComConEventSendFirst     = 0x00, // first frame to send
114     kEplSdoComConEventRec           = 0x01, // frame received
115     kEplSdoComConEventConEstablished= 0x02, // connection established
116     kEplSdoComConEventConClosed     = 0x03, // connection closed
117     kEplSdoComConEventAckReceived   = 0x04, // acknowledge received by lower layer
118                                         // -> continue sending
119     kEplSdoComConEventFrameSended   = 0x05, // lower has send a frame
120     kEplSdoComConEventInitError     = 0x06, // error duringinitialisiation
121                                             // of the connection
122     kEplSdoComConEventTimeout       = 0x07 // timeout in lower layer
123 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
124
125     ,
126
127     kEplSdoComConEventInitCon       = 0x08, // init connection (only client)
128     kEplSdoComConEventAbort         = 0x09 // abort sdo transfer (only client)
129 #endif
130
131
132 }tEplSdoComConEvent;
133
134 typedef enum
135 {
136     kEplSdoComSendTypeReq      = 0x00,  // send a request
137     kEplSdoComSendTypeAckRes   = 0x01,  // send a resonse without data
138     kEplSdoComSendTypeRes      = 0x02,  // send response with data
139     kEplSdoComSendTypeAbort    = 0x03   // send abort
140
141 }tEplSdoComSendType;
142
143 // state of the state maschine
144 typedef enum
145 {
146     // General State
147     kEplSdoComStateIdle             = 0x00, // idle state
148
149 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
150     // Server States
151     kEplSdoComStateServerSegmTrans  = 0x01, // send following frames
152 #endif
153
154
155 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
156     // Client States
157     kEplSdoComStateClientWaitInit   = 0x10, // wait for init connection
158                                             // on lower layer
159     kEplSdoComStateClientConnected  = 0x11, // connection established
160     kEplSdoComStateClientSegmTrans  = 0x12  // send following frames
161 #endif
162
163
164
165 } tEplSdoComState;
166
167
168 // control structure for transaction
169 typedef struct
170 {
171     tEplSdoSeqConHdl    m_SdoSeqConHdl;     // if != 0 -> entry used
172     tEplSdoComState     m_SdoComState;
173     BYTE                m_bTransactionId;
174     unsigned int        m_uiNodeId;         // NodeId of the target
175                                             // -> needed to reinit connection
176                                             //    after timeout
177     tEplSdoTransType    m_SdoTransType;     // Auto, Expedited, Segmented
178     tEplSdoServiceType  m_SdoServiceType;   // WriteByIndex, ReadByIndex
179     tEplSdoType         m_SdoProtType;      // protocol layer: Auto, Udp, Asnd, Pdo
180     BYTE*               m_pData;            // pointer to data
181     unsigned int        m_uiTransSize;      // number of bytes
182                                             // to transfer
183     unsigned int        m_uiTransferredByte;// number of bytes
184                                             // already transferred
185     tEplSdoFinishedCb   m_pfnTransferFinished;// callback function of the
186                                             // application
187                                             // -> called in the end of
188                                             //    the SDO transfer
189     void*               m_pUserArg;         // user definable argument pointer
190
191     DWORD               m_dwLastAbortCode;  // save the last abort code
192 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
193     // only for client
194     unsigned int        m_uiTargetIndex;    // index to access
195     unsigned int        m_uiTargetSubIndex; // subiondex to access
196
197     // for future use
198     unsigned int        m_uiTimeout;        // timeout for this connection
199
200 #endif
201
202 } tEplSdoComCon;
203
204 // instance table
205 typedef struct
206 {
207     tEplSdoComCon       m_SdoComCon[EPL_MAX_SDO_COM_CON];
208
209 #if defined(WIN32) || defined(_WIN32)
210     LPCRITICAL_SECTION  m_pCriticalSection;
211     CRITICAL_SECTION    m_CriticalSection;
212 #endif
213
214 }tEplSdoComInstance;
215
216 //---------------------------------------------------------------------------
217 // modul globale vars
218 //---------------------------------------------------------------------------
219 static tEplSdoComInstance SdoComInstance_g;
220 //---------------------------------------------------------------------------
221 // local function prototypes
222 //---------------------------------------------------------------------------
223 tEplKernel PUBLIC EplSdoComReceiveCb (tEplSdoSeqConHdl    SdoSeqConHdl_p,
224                                     tEplAsySdoCom*      pAsySdoCom_p,
225                                     unsigned int        uiDataSize_p);
226
227
228 tEplKernel PUBLIC EplSdoComConCb (tEplSdoSeqConHdl    SdoSeqConHdl_p,
229                                     tEplAsySdoConState  AsySdoConState_p);
230
231 static tEplKernel EplSdoComSearchConIntern(tEplSdoSeqConHdl    SdoSeqConHdl_p,
232                                          tEplSdoComConEvent SdoComConEvent_p,
233                                          tEplAsySdoCom*     pAsySdoCom_p);
234
235 static tEplKernel EplSdoComProcessIntern(tEplSdoComConHdl   SdoComCon_p,
236                                          tEplSdoComConEvent SdoComConEvent_p,
237                                          tEplAsySdoCom*     pAsySdoCom_p);
238
239 static tEplKernel EplSdoComTransferFinished(tEplSdoComConHdl   SdoComCon_p,
240                                             tEplSdoComCon*     pSdoComCon_p,
241                                             tEplSdoComConState SdoComConState_p);
242
243 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
244 static tEplKernel EplSdoComServerInitReadByIndex(tEplSdoComCon*     pSdoComCon_p,
245                                          tEplAsySdoCom*     pAsySdoCom_p);
246
247 static tEplKernel EplSdoComServerSendFrameIntern(tEplSdoComCon*     pSdoComCon_p,
248                                            unsigned int       uiIndex_p,
249                                            unsigned int       uiSubIndex_p,
250                                            tEplSdoComSendType SendType_p);
251
252 static tEplKernel EplSdoComServerInitWriteByIndex(tEplSdoComCon*     pSdoComCon_p,
253                                          tEplAsySdoCom*     pAsySdoCom_p);
254 #endif
255
256
257 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
258
259 static tEplKernel EplSdoComClientSend(tEplSdoComCon* pSdoComCon_p);
260
261 static tEplKernel EplSdoComClientProcessFrame(tEplSdoComConHdl   SdoComCon_p,
262                                               tEplAsySdoCom*     pAsySdoCom_p);
263
264 static tEplKernel EplSdoComClientSendAbort(tEplSdoComCon* pSdoComCon_p,
265                                            DWORD          dwAbortCode_p);
266 #endif
267
268
269
270 /***************************************************************************/
271 /*                                                                         */
272 /*                                                                         */
273 /*          C L A S S  <SDO Command Layer>                                 */
274 /*                                                                         */
275 /*                                                                         */
276 /***************************************************************************/
277 //
278 // Description: SDO Command layer Modul
279 //
280 //
281 /***************************************************************************/
282
283 //=========================================================================//
284 //                                                                         //
285 //          P U B L I C   F U N C T I O N S                                //
286 //                                                                         //
287 //=========================================================================//
288
289 //---------------------------------------------------------------------------
290 //
291 // Function:    EplSdoComInit
292 //
293 // Description: Init first instance of the module
294 //
295 //
296 //
297 // Parameters:
298 //
299 //
300 // Returns:     tEplKernel  = errorcode
301 //
302 //
303 // State:
304 //
305 //---------------------------------------------------------------------------
306 tEplKernel PUBLIC EplSdoComInit(void)
307 {
308 tEplKernel  Ret;
309
310
311     Ret = EplSdoComAddInstance();
312
313 return Ret;
314
315 }
316
317 //---------------------------------------------------------------------------
318 //
319 // Function:    EplSdoComAddInstance
320 //
321 // Description: Init additional instance of the module
322 //
323 //
324 //
325 // Parameters:
326 //
327 //
328 // Returns:     tEplKernel  = errorcode
329 //
330 //
331 // State:
332 //
333 //---------------------------------------------------------------------------
334 tEplKernel PUBLIC EplSdoComAddInstance(void)
335 {
336 tEplKernel Ret;
337
338     Ret = kEplSuccessful;
339
340     // init controll structure
341     EPL_MEMSET(&SdoComInstance_g, 0x00, sizeof(SdoComInstance_g));
342
343     // init instance of lower layer
344     Ret = EplSdoAsySeqAddInstance(EplSdoComReceiveCb, EplSdoComConCb);
345     if(Ret != kEplSuccessful)
346     {
347         goto Exit;
348     }
349
350 #if defined(WIN32) || defined(_WIN32)
351     // create critical section for process function
352     SdoComInstance_g.m_pCriticalSection = &SdoComInstance_g.m_CriticalSection;
353     InitializeCriticalSection(SdoComInstance_g.m_pCriticalSection);
354 #endif
355
356 Exit:
357     return Ret;
358 }
359
360 //---------------------------------------------------------------------------
361 //
362 // Function:    EplSdoComDelInstance
363 //
364 // Description: delete instance of the module
365 //
366 //
367 //
368 // Parameters:
369 //
370 //
371 // Returns:     tEplKernel  = errorcode
372 //
373 //
374 // State:
375 //
376 //---------------------------------------------------------------------------
377 tEplKernel PUBLIC EplSdoComDelInstance(void)
378 {
379 tEplKernel  Ret;
380
381     Ret = kEplSuccessful;
382
383
384 #if defined(WIN32) || defined(_WIN32)
385     // delete critical section for process function
386     DeleteCriticalSection(SdoComInstance_g.m_pCriticalSection);
387 #endif
388
389     Ret = EplSdoAsySeqDelInstance();
390     if(Ret != kEplSuccessful)
391     {
392         goto Exit;
393     }
394
395
396 Exit:
397     return Ret;
398 }
399
400 //---------------------------------------------------------------------------
401 //
402 // Function:    EplSdoComDefineCon
403 //
404 // Description: function defines a SDO connection to another node
405 //              -> init lower layer and returns a handle for the connection.
406 //              Two client connections to the same node via the same protocol
407 //              are not allowed. If this function detects such a situation
408 //              it will return kEplSdoComHandleExists and the handle of
409 //              the existing connection in pSdoComConHdl_p.
410 //              Using of existing server connections is possible.
411 //
412 // Parameters:  pSdoComConHdl_p     = pointer to the buffer of the handle
413 //              uiTargetNodeId_p    = NodeId of the targetnode
414 //              ProtType_p          = type of protocol to use for connection
415 //
416 //
417 // Returns:     tEplKernel  = errorcode
418 //
419 //
420 // State:
421 //
422 //---------------------------------------------------------------------------
423 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
424 tEplKernel PUBLIC EplSdoComDefineCon(tEplSdoComConHdl*  pSdoComConHdl_p,
425                                       unsigned int      uiTargetNodeId_p,
426                                       tEplSdoType       ProtType_p)
427 {
428 tEplKernel      Ret;
429 unsigned int    uiCount;
430 unsigned int    uiFreeHdl;
431 tEplSdoComCon*  pSdoComCon;
432
433     // check Parameter
434     ASSERT(pSdoComConHdl_p != NULL);
435
436     // check NodeId
437     if((uiTargetNodeId_p == EPL_C_ADR_INVALID)
438         ||(uiTargetNodeId_p >= EPL_C_ADR_BROADCAST))
439     {
440         Ret = kEplInvalidNodeId;
441
442     }
443
444     // search free control structure
445     pSdoComCon = &SdoComInstance_g.m_SdoComCon[0];
446     uiCount = 0;
447     uiFreeHdl = EPL_MAX_SDO_COM_CON;
448     while (uiCount < EPL_MAX_SDO_COM_CON)
449     {
450         if (pSdoComCon->m_SdoSeqConHdl == 0)
451         {   // free entry
452             uiFreeHdl = uiCount;
453         }
454         else if ((pSdoComCon->m_uiNodeId == uiTargetNodeId_p)
455             && (pSdoComCon->m_SdoProtType == ProtType_p))
456         {   // existing client connection with same node ID and same protocol type
457             *pSdoComConHdl_p = uiCount;
458             Ret = kEplSdoComHandleExists;
459             goto Exit;
460         }
461         uiCount++;
462         pSdoComCon++;
463     }
464
465     if (uiFreeHdl == EPL_MAX_SDO_COM_CON)
466     {
467         Ret = kEplSdoComNoFreeHandle;
468         goto Exit;
469     }
470
471     pSdoComCon = &SdoComInstance_g.m_SdoComCon[uiFreeHdl];
472     // save handle for application
473     *pSdoComConHdl_p = uiFreeHdl;
474     // save parameters
475     pSdoComCon->m_SdoProtType = ProtType_p;
476     pSdoComCon->m_uiNodeId = uiTargetNodeId_p;
477
478     // set Transaction Id
479     pSdoComCon->m_bTransactionId = 0;
480
481     // check protocol
482     switch(ProtType_p)
483     {
484         // udp
485         case kEplSdoTypeUdp:
486         {
487             // call connection int function of lower layer
488             Ret = EplSdoAsySeqInitCon(&pSdoComCon->m_SdoSeqConHdl,
489                           pSdoComCon->m_uiNodeId,
490                           kEplSdoTypeUdp);
491             if(Ret != kEplSuccessful)
492             {
493                 goto Exit;
494             }
495             break;
496         }
497
498         // Asend
499         case kEplSdoTypeAsnd:
500         {
501             // call connection int function of lower layer
502             Ret = EplSdoAsySeqInitCon(&pSdoComCon->m_SdoSeqConHdl,
503                           pSdoComCon->m_uiNodeId,
504                           kEplSdoTypeAsnd);
505             if(Ret != kEplSuccessful)
506             {
507                 goto Exit;
508             }
509             break;
510         }
511
512         // Pdo -> not supported
513         case kEplSdoTypePdo:
514         default:
515         {
516             Ret = kEplSdoComUnsupportedProt;
517             goto Exit;
518         }
519     }// end of switch(m_ProtType_p)
520
521     // call process function
522     Ret = EplSdoComProcessIntern(uiFreeHdl,
523                                     kEplSdoComConEventInitCon,
524                                     NULL);
525
526 Exit:
527     return Ret;
528 }
529 #endif
530 //---------------------------------------------------------------------------
531 //
532 // Function:    EplSdoComInitTransferByIndex
533 //
534 // Description: function init SDO Transfer for a defined connection
535 //
536 //
537 //
538 // Parameters:  SdoComTransParam_p    = Structure with parameters for connection
539 //
540 //
541 // Returns:     tEplKernel  = errorcode
542 //
543 //
544 // State:
545 //
546 //---------------------------------------------------------------------------
547 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
548 tEplKernel PUBLIC EplSdoComInitTransferByIndex(tEplSdoComTransParamByIndex* pSdoComTransParam_p)
549 {
550 tEplKernel      Ret;
551 tEplSdoComCon*  pSdoComCon;
552
553     // check parameter
554     if ((pSdoComTransParam_p->m_uiSubindex >= 0xFF)
555         || (pSdoComTransParam_p->m_uiIndex == 0)
556         || (pSdoComTransParam_p->m_uiIndex > 0xFFFF)
557         || (pSdoComTransParam_p->m_pData == NULL)
558         || (pSdoComTransParam_p->m_uiDataSize == 0))
559     {
560         Ret = kEplSdoComInvalidParam;
561         goto Exit;
562     }
563
564     if(pSdoComTransParam_p->m_SdoComConHdl >= EPL_MAX_SDO_COM_CON)
565     {
566         Ret = kEplSdoComInvalidHandle;
567         goto Exit;
568     }
569
570     // get pointer to control structure of connection
571     pSdoComCon = &SdoComInstance_g.m_SdoComCon[pSdoComTransParam_p->m_SdoComConHdl];
572
573     // check if handle ok
574     if(pSdoComCon->m_SdoSeqConHdl == 0)
575     {
576         Ret = kEplSdoComInvalidHandle;
577         goto Exit;
578     }
579
580     // check if command layer is idle
581     if ((pSdoComCon->m_uiTransferredByte + pSdoComCon->m_uiTransSize) > 0)
582     {   // handle is not idle
583         Ret = kEplSdoComHandleBusy;
584         goto Exit;
585     }
586
587     // save parameter
588     // callback function for end of transfer
589     pSdoComCon->m_pfnTransferFinished = pSdoComTransParam_p->m_pfnSdoFinishedCb;
590     pSdoComCon->m_pUserArg = pSdoComTransParam_p->m_pUserArg;
591
592     // set type of SDO command
593     if (pSdoComTransParam_p->m_SdoAccessType == kEplSdoAccessTypeRead)
594     {
595         pSdoComCon->m_SdoServiceType = kEplSdoServiceReadByIndex;
596     }
597     else
598     {
599         pSdoComCon->m_SdoServiceType = kEplSdoServiceWriteByIndex;
600
601     }
602     // save pointer to data
603     pSdoComCon->m_pData = pSdoComTransParam_p->m_pData;
604     // maximal bytes to transfer
605     pSdoComCon->m_uiTransSize = pSdoComTransParam_p->m_uiDataSize;
606     // bytes already transfered
607     pSdoComCon->m_uiTransferredByte = 0;
608
609     // reset parts of control structure
610     pSdoComCon->m_dwLastAbortCode = 0;
611     pSdoComCon->m_SdoTransType = kEplSdoTransAuto;
612     // save timeout
613     //pSdoComCon->m_uiTimeout = SdoComTransParam_p.m_uiTimeout;
614
615     // save index and subindex
616     pSdoComCon->m_uiTargetIndex = pSdoComTransParam_p->m_uiIndex;
617     pSdoComCon->m_uiTargetSubIndex = pSdoComTransParam_p->m_uiSubindex;
618
619     // call process function
620     Ret = EplSdoComProcessIntern(pSdoComTransParam_p->m_SdoComConHdl,
621                                     kEplSdoComConEventSendFirst,    // event to start transfer
622                                     NULL);
623
624 Exit:
625     return Ret;
626
627 }
628 #endif
629
630 //---------------------------------------------------------------------------
631 //
632 // Function:    EplSdoComUndefineCon
633 //
634 // Description: function undefine a SDO connection
635 //
636 //
637 //
638 // Parameters:  SdoComConHdl_p    = handle for the connection
639 //
640 //
641 // Returns:     tEplKernel  = errorcode
642 //
643 //
644 // State:
645 //
646 //---------------------------------------------------------------------------
647 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
648 tEplKernel PUBLIC EplSdoComUndefineCon(tEplSdoComConHdl  SdoComConHdl_p)
649 {
650 tEplKernel          Ret;
651 tEplSdoComCon*      pSdoComCon;
652
653     Ret = kEplSuccessful;
654
655     if(SdoComConHdl_p >= EPL_MAX_SDO_COM_CON)
656     {
657         Ret = kEplSdoComInvalidHandle;
658         goto Exit;
659     }
660
661     // get pointer to control structure
662     pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComConHdl_p];
663
664     // $$$ d.k. abort a running transfer before closing the sequence layer
665
666     if(((pSdoComCon->m_SdoSeqConHdl & ~EPL_SDO_SEQ_HANDLE_MASK)  != EPL_SDO_SEQ_INVALID_HDL)
667         && (pSdoComCon->m_SdoSeqConHdl != 0))
668     {
669         // close connection in lower layer
670         switch(pSdoComCon->m_SdoProtType)
671         {
672             case kEplSdoTypeAsnd:
673             case kEplSdoTypeUdp:
674             {
675                 Ret = EplSdoAsySeqDelCon(pSdoComCon->m_SdoSeqConHdl);
676                 break;
677             }
678
679             case kEplSdoTypePdo:
680             case kEplSdoTypeAuto:
681             default:
682             {
683                 Ret = kEplSdoComUnsupportedProt;
684                 goto Exit;
685             }
686
687         }// end of switch(pSdoComCon->m_SdoProtType)
688     }
689
690
691     // clean controll structure
692     EPL_MEMSET(pSdoComCon, 0x00, sizeof(tEplSdoComCon));
693 Exit:
694     return Ret;
695 }
696 #endif
697 //---------------------------------------------------------------------------
698 //
699 // Function:    EplSdoComGetState
700 //
701 // Description: function returns the state fo the connection
702 //
703 //
704 //
705 // Parameters:  SdoComConHdl_p    = handle for the connection
706 //              pSdoComFinished_p = pointer to structur for sdo state
707 //
708 //
709 // Returns:     tEplKernel  = errorcode
710 //
711 //
712 // State:
713 //
714 //---------------------------------------------------------------------------
715 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
716 tEplKernel PUBLIC EplSdoComGetState(tEplSdoComConHdl    SdoComConHdl_p,
717                                     tEplSdoComFinished* pSdoComFinished_p)
718 {
719 tEplKernel          Ret;
720 tEplSdoComCon*      pSdoComCon;
721
722     Ret = kEplSuccessful;
723
724     if(SdoComConHdl_p >= EPL_MAX_SDO_COM_CON)
725     {
726         Ret = kEplSdoComInvalidHandle;
727         goto Exit;
728     }
729
730     // get pointer to control structure
731     pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComConHdl_p];
732
733     // check if handle ok
734     if(pSdoComCon->m_SdoSeqConHdl == 0)
735     {
736         Ret = kEplSdoComInvalidHandle;
737         goto Exit;
738     }
739
740     pSdoComFinished_p->m_pUserArg = pSdoComCon->m_pUserArg;
741     pSdoComFinished_p->m_uiNodeId = pSdoComCon->m_uiNodeId;
742     pSdoComFinished_p->m_uiTargetIndex = pSdoComCon->m_uiTargetIndex;
743     pSdoComFinished_p->m_uiTargetSubIndex = pSdoComCon->m_uiTargetSubIndex;
744     pSdoComFinished_p->m_uiTransferredByte = pSdoComCon->m_uiTransferredByte;
745     pSdoComFinished_p->m_dwAbortCode = pSdoComCon->m_dwLastAbortCode;
746     pSdoComFinished_p->m_SdoComConHdl = SdoComConHdl_p;
747     if (pSdoComCon->m_SdoServiceType == kEplSdoServiceWriteByIndex)
748     {
749         pSdoComFinished_p->m_SdoAccessType = kEplSdoAccessTypeWrite;
750     }
751     else
752     {
753         pSdoComFinished_p->m_SdoAccessType = kEplSdoAccessTypeRead;
754     }
755
756     if(pSdoComCon->m_dwLastAbortCode != 0)
757     {   // sdo abort
758         pSdoComFinished_p->m_SdoComConState = kEplSdoComTransferRxAborted;
759
760         // delete abort code
761         pSdoComCon->m_dwLastAbortCode = 0;
762
763     }
764     else if((pSdoComCon->m_SdoSeqConHdl & ~EPL_SDO_SEQ_HANDLE_MASK)== EPL_SDO_SEQ_INVALID_HDL)
765     {   // check state
766         pSdoComFinished_p->m_SdoComConState = kEplSdoComTransferLowerLayerAbort;
767     }
768     else if(pSdoComCon->m_SdoComState == kEplSdoComStateClientWaitInit)
769     {
770         // finished
771         pSdoComFinished_p->m_SdoComConState = kEplSdoComTransferNotActive;
772     }
773     else if(pSdoComCon->m_uiTransSize == 0)
774     {   // finished
775         pSdoComFinished_p->m_SdoComConState = kEplSdoComTransferFinished;
776     }
777
778 Exit:
779     return Ret;
780
781 }
782 #endif
783 //---------------------------------------------------------------------------
784 //
785 // Function:    EplSdoComSdoAbort
786 //
787 // Description: function abort a sdo transfer
788 //
789 //
790 //
791 // Parameters:  SdoComConHdl_p    = handle for the connection
792 //              dwAbortCode_p     = abort code
793 //
794 //
795 // Returns:     tEplKernel  = errorcode
796 //
797 //
798 // State:
799 //
800 //---------------------------------------------------------------------------
801 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
802 tEplKernel PUBLIC EplSdoComSdoAbort(tEplSdoComConHdl SdoComConHdl_p,
803                                     DWORD            dwAbortCode_p)
804 {
805 tEplKernel  Ret;
806 tEplSdoComCon*      pSdoComCon;
807
808
809     if(SdoComConHdl_p >= EPL_MAX_SDO_COM_CON)
810     {
811         Ret = kEplSdoComInvalidHandle;
812         goto Exit;
813     }
814
815     // get pointer to control structure of connection
816     pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComConHdl_p];
817
818     // check if handle ok
819     if(pSdoComCon->m_SdoSeqConHdl == 0)
820     {
821         Ret = kEplSdoComInvalidHandle;
822         goto Exit;
823     }
824
825     // save pointer to abort code
826     pSdoComCon->m_pData = (BYTE*)&dwAbortCode_p;
827
828     Ret = EplSdoComProcessIntern(SdoComConHdl_p,
829                                 kEplSdoComConEventAbort,
830                                 (tEplAsySdoCom*)NULL);
831
832 Exit:
833     return Ret;
834 }
835 #endif
836
837 //=========================================================================//
838 //                                                                         //
839 //          P R I V A T E   F U N C T I O N S                              //
840 //                                                                         //
841 //=========================================================================//
842
843 //---------------------------------------------------------------------------
844 //
845 // Function:        EplSdoComReceiveCb
846 //
847 // Description:     callback function for SDO Sequence Layer
848 //                  -> indicates new data
849 //
850 //
851 //
852 // Parameters:      SdoSeqConHdl_p = Handle for connection
853 //                  pAsySdoCom_p   = pointer to data
854 //                  uiDataSize_p   = size of data ($$$ not used yet, but it should)
855 //
856 //
857 // Returns:
858 //
859 //
860 // State:
861 //
862 //---------------------------------------------------------------------------
863 tEplKernel PUBLIC EplSdoComReceiveCb (tEplSdoSeqConHdl    SdoSeqConHdl_p,
864                                     tEplAsySdoCom*      pAsySdoCom_p,
865                                     unsigned int        uiDataSize_p)
866 {
867 tEplKernel       Ret;
868
869
870     // search connection internally
871     Ret = EplSdoComSearchConIntern(SdoSeqConHdl_p,
872                                    kEplSdoComConEventRec,
873                                    pAsySdoCom_p);
874
875     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);
876
877     return Ret;
878 }
879
880 //---------------------------------------------------------------------------
881 //
882 // Function:        EplSdoComConCb
883 //
884 // Description:     callback function called by SDO Sequence Layer to inform
885 //                  command layer about state change of connection
886 //
887 //
888 //
889 // Parameters:      SdoSeqConHdl_p      = Handle of the connection
890 //                  AsySdoConState_p    = Event of the connection
891 //
892 //
893 // Returns:         tEplKernel  = Errorcode
894 //
895 //
896 // State:
897 //
898 //---------------------------------------------------------------------------
899 tEplKernel PUBLIC EplSdoComConCb (tEplSdoSeqConHdl    SdoSeqConHdl_p,
900                                     tEplAsySdoConState  AsySdoConState_p)
901 {
902 tEplKernel          Ret;
903 tEplSdoComConEvent  SdoComConEvent = kEplSdoComConEventSendFirst;
904
905     Ret = kEplSuccessful;
906
907     // check state
908     switch(AsySdoConState_p)
909     {
910         case kAsySdoConStateConnected:
911         {
912             EPL_DBGLVL_SDO_TRACE0("Connection established\n");
913             SdoComConEvent = kEplSdoComConEventConEstablished;
914             // start transmission if needed
915             break;
916         }
917
918         case kAsySdoConStateInitError:
919         {
920             EPL_DBGLVL_SDO_TRACE0("Error during initialisation\n");
921             SdoComConEvent = kEplSdoComConEventInitError;
922             // inform app about error and close sequence layer handle
923             break;
924         }
925
926         case kAsySdoConStateConClosed:
927         {
928             EPL_DBGLVL_SDO_TRACE0("Connection closed\n");
929             SdoComConEvent = kEplSdoComConEventConClosed;
930             // close sequence layer handle
931             break;
932         }
933
934         case kAsySdoConStateAckReceived:
935         {
936             EPL_DBGLVL_SDO_TRACE0("Acknowlage received\n");
937             SdoComConEvent = kEplSdoComConEventAckReceived;
938             // continue transmission
939             break;
940         }
941
942         case kAsySdoConStateFrameSended:
943         {
944             EPL_DBGLVL_SDO_TRACE0("One Frame sent\n");
945             SdoComConEvent = kEplSdoComConEventFrameSended;
946             // to continue transmission
947             break;
948
949         }
950
951         case kAsySdoConStateTimeout:
952         {
953             EPL_DBGLVL_SDO_TRACE0("Timeout\n");
954             SdoComConEvent = kEplSdoComConEventTimeout;
955             // close sequence layer handle
956             break;
957
958         }
959     }// end of switch(AsySdoConState_p)
960
961     Ret = EplSdoComSearchConIntern(SdoSeqConHdl_p,
962                                    SdoComConEvent,
963                                    (tEplAsySdoCom*)NULL);
964
965     return Ret;
966 }
967
968 //---------------------------------------------------------------------------
969 //
970 // Function:        EplSdoComSearchConIntern
971 //
972 // Description:     search a Sdo Sequence Layer connection handle in the
973 //                  control structure of the Command Layer
974 //
975 // Parameters:      SdoSeqConHdl_p     = Handle to search
976 //                  SdoComConEvent_p = event to process
977 //                  pAsySdoCom_p     = pointer to received frame
978 //
979 // Returns:         tEplKernel
980 //
981 //
982 // State:
983 //
984 //---------------------------------------------------------------------------
985 static tEplKernel EplSdoComSearchConIntern(tEplSdoSeqConHdl    SdoSeqConHdl_p,
986                                          tEplSdoComConEvent SdoComConEvent_p,
987                                          tEplAsySdoCom*     pAsySdoCom_p)
988 {
989 tEplKernel          Ret;
990 tEplSdoComCon*      pSdoComCon;
991 tEplSdoComConHdl    HdlCount;
992 tEplSdoComConHdl    HdlFree;
993
994     Ret = kEplSdoComNotResponsible;
995
996     // get pointer to first element of the array
997     pSdoComCon = &SdoComInstance_g.m_SdoComCon[0];
998     HdlCount = 0;
999     HdlFree = 0xFFFF;
1000     while (HdlCount < EPL_MAX_SDO_COM_CON)
1001     {
1002         if (pSdoComCon->m_SdoSeqConHdl == SdoSeqConHdl_p)
1003         {   // matching command layer handle found
1004             Ret = EplSdoComProcessIntern(HdlCount,
1005                                     SdoComConEvent_p,
1006                                     pAsySdoCom_p);
1007         }
1008         else if ((pSdoComCon->m_SdoSeqConHdl == 0)
1009             &&(HdlFree == 0xFFFF))
1010         {
1011             HdlFree = HdlCount;
1012         }
1013
1014         pSdoComCon++;
1015         HdlCount++;
1016     }
1017
1018     if (Ret == kEplSdoComNotResponsible)
1019     {   // no responsible command layer handle found
1020         if (HdlFree == 0xFFFF)
1021         {   // no free handle
1022             // delete connection immediately
1023             // 2008/04/14 m.u./d.k. This connection actually does not exist.
1024             //                      pSdoComCon is invalid.
1025             // Ret = EplSdoAsySeqDelCon(pSdoComCon->m_SdoSeqConHdl);
1026             Ret = kEplSdoComNoFreeHandle;
1027         }
1028         else
1029         {   // create new handle
1030             HdlCount = HdlFree;
1031             pSdoComCon = &SdoComInstance_g.m_SdoComCon[HdlCount];
1032             pSdoComCon->m_SdoSeqConHdl = SdoSeqConHdl_p;
1033             Ret = EplSdoComProcessIntern(HdlCount,
1034                                     SdoComConEvent_p,
1035                                     pAsySdoCom_p);
1036         }
1037     }
1038
1039     return Ret;
1040
1041 }
1042
1043 //---------------------------------------------------------------------------
1044 //
1045 // Function:        EplSdoComProcessIntern
1046 //
1047 // Description:     search a Sdo Sequence Layer connection handle in the
1048 //                  control structer of the Command Layer
1049 //
1050 //
1051 //
1052 // Parameters:      SdoComCon_p     = index of control structure of connection
1053 //                  SdoComConEvent_p = event to process
1054 //                  pAsySdoCom_p     = pointer to received frame
1055 //
1056 // Returns:         tEplKernel  =  errorcode
1057 //
1058 //
1059 // State:
1060 //
1061 //---------------------------------------------------------------------------
1062 static tEplKernel EplSdoComProcessIntern(tEplSdoComConHdl   SdoComCon_p,
1063                                          tEplSdoComConEvent SdoComConEvent_p,
1064                                          tEplAsySdoCom*     pAsySdoCom_p)
1065 {
1066 tEplKernel          Ret;
1067 tEplSdoComCon*      pSdoComCon;
1068 BYTE                bFlag;
1069
1070 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
1071 DWORD               dwAbortCode;
1072 unsigned int        uiSize;
1073 #endif
1074
1075 #if defined(WIN32) || defined(_WIN32)
1076     // enter  critical section for process function
1077     EnterCriticalSection(SdoComInstance_g.m_pCriticalSection);
1078     EPL_DBGLVL_SDO_TRACE0("\n\tEnterCiticalSection EplSdoComProcessIntern\n\n");
1079 #endif
1080
1081     Ret = kEplSuccessful;
1082
1083     // get pointer to control structure
1084     pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComCon_p];
1085
1086     // process state maschine
1087     switch(pSdoComCon->m_SdoComState)
1088     {
1089         // idle state
1090         case kEplSdoComStateIdle:
1091         {
1092             // check events
1093             switch(SdoComConEvent_p)
1094             {
1095 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
1096                 // init con for client
1097                 case kEplSdoComConEventInitCon:
1098                 {
1099
1100                     // call of the init function already
1101                     // processed in EplSdoComDefineCon()
1102                     // only change state to kEplSdoComStateClientWaitInit
1103                     pSdoComCon->m_SdoComState = kEplSdoComStateClientWaitInit;
1104                     break;
1105                 }
1106 #endif
1107
1108
1109                 // int con for server
1110                 case kEplSdoComConEventRec:
1111                 {
1112 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
1113                     // check if init of an transfer and no SDO abort
1114                     if ((pAsySdoCom_p->m_le_bFlags & 0x80) == 0)
1115                     {   // SDO request
1116                         if ((pAsySdoCom_p->m_le_bFlags & 0x40) == 0)
1117                         {   // no SDO abort
1118                             // save tansaction id
1119                             pSdoComCon->m_bTransactionId = AmiGetByteFromLe(&pAsySdoCom_p->m_le_bTransactionId);
1120                             // check command
1121                             switch(pAsySdoCom_p->m_le_bCommandId)
1122                             {
1123                                 case kEplSdoServiceNIL:
1124                                 {   // simply acknowlegde NIL command on sequence layer
1125
1126                                     Ret = EplSdoAsySeqSendData(pSdoComCon->m_SdoSeqConHdl,
1127                                                                             0,
1128                                                                             (tEplFrame*)NULL);
1129
1130                                     break;
1131                                 }
1132
1133                                 case kEplSdoServiceReadByIndex:
1134                                 {   // read by index
1135
1136                                     // search entry an start transfer
1137                                     EplSdoComServerInitReadByIndex(pSdoComCon,
1138                                                                     pAsySdoCom_p);
1139                                     // check next state
1140                                     if(pSdoComCon->m_uiTransSize == 0)
1141                                     {   // ready -> stay idle
1142                                         pSdoComCon->m_SdoComState = kEplSdoComStateIdle;
1143                                         // reset abort code
1144                                         pSdoComCon->m_dwLastAbortCode = 0;
1145                                     }
1146                                     else
1147                                     {   // segmented transfer
1148                                         pSdoComCon->m_SdoComState = kEplSdoComStateServerSegmTrans;
1149                                     }
1150
1151                                     break;
1152                                 }
1153
1154                                 case kEplSdoServiceWriteByIndex:
1155                                 {
1156
1157                                     // search entry an start write
1158                                     EplSdoComServerInitWriteByIndex(pSdoComCon,
1159                                                                     pAsySdoCom_p);
1160                                     // check next state
1161                                     if(pSdoComCon->m_uiTransSize == 0)
1162                                     {   // already -> stay idle
1163                                         pSdoComCon->m_SdoComState = kEplSdoComStateIdle;
1164                                         // reset abort code
1165                                         pSdoComCon->m_dwLastAbortCode = 0;
1166                                     }
1167                                     else
1168                                     {   // segmented transfer
1169                                         pSdoComCon->m_SdoComState = kEplSdoComStateServerSegmTrans;
1170                                     }
1171
1172                                     break;
1173                                 }
1174
1175                                 default:
1176                                 {
1177                                     //  unsupported command
1178                                     //       -> abort senden
1179                                     dwAbortCode = EPL_SDOAC_UNKNOWN_COMMAND_SPECIFIER;
1180                                     // send abort
1181                                     pSdoComCon->m_pData = (BYTE*)&dwAbortCode;
1182                                     Ret = EplSdoComServerSendFrameIntern(pSdoComCon,
1183                                                                 0,
1184                                                                 0,
1185                                                                 kEplSdoComSendTypeAbort);
1186
1187                                 }
1188
1189
1190                             }// end of switch(pAsySdoCom_p->m_le_bCommandId)
1191                         }
1192                     }
1193                     else
1194                     {   // this command layer handle is not responsible
1195                         // (wrong direction or wrong transaction ID)
1196                         Ret = kEplSdoComNotResponsible;
1197                         goto Exit;
1198                     }
1199 #endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
1200
1201                     break;
1202                 }
1203
1204                 // connection closed
1205                 case kEplSdoComConEventInitError:
1206                 case kEplSdoComConEventTimeout:
1207                 case kEplSdoComConEventConClosed:
1208                 {
1209                     Ret = EplSdoAsySeqDelCon(pSdoComCon->m_SdoSeqConHdl);
1210                     // clean control structure
1211                     EPL_MEMSET(pSdoComCon, 0x00, sizeof(tEplSdoComCon));
1212                     break;
1213                 }
1214
1215                 default:
1216                     // d.k. do nothing
1217                     break;
1218             }// end of switch(SdoComConEvent_p)
1219             break;
1220         }
1221
1222 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
1223         //-------------------------------------------------------------------------
1224         // SDO Server part
1225         // segmented transfer
1226         case kEplSdoComStateServerSegmTrans:
1227         {
1228             // check events
1229             switch(SdoComConEvent_p)
1230             {
1231                 // send next frame
1232                 case kEplSdoComConEventAckReceived:
1233                 case kEplSdoComConEventFrameSended:
1234                 {
1235                     // check if it is a read
1236                     if(pSdoComCon->m_SdoServiceType == kEplSdoServiceReadByIndex)
1237                     {
1238                         // send next frame
1239                         EplSdoComServerSendFrameIntern(pSdoComCon,
1240                                                             0,
1241                                                             0,
1242                                                             kEplSdoComSendTypeRes);
1243                         // if all send -> back to idle
1244                         if(pSdoComCon->m_uiTransSize == 0)
1245                         {   // back to idle
1246                             pSdoComCon->m_SdoComState = kEplSdoComStateIdle;
1247                             // reset abort code
1248                             pSdoComCon->m_dwLastAbortCode = 0;
1249                         }
1250
1251                     }
1252                     break;
1253                 }
1254
1255                 // process next frame
1256                 case kEplSdoComConEventRec:
1257                 {
1258                     // check if the frame is a SDO response and has the right transaction ID
1259                     bFlag = AmiGetByteFromLe(&pAsySdoCom_p->m_le_bFlags);
1260                     if (((bFlag & 0x80) != 0) && (AmiGetByteFromLe(&pAsySdoCom_p->m_le_bTransactionId) == pSdoComCon->m_bTransactionId))
1261                     {
1262                         // check if it is a abort
1263                         if((bFlag & 0x40) != 0)
1264                         {   // SDO abort
1265                             // clear control structure
1266                             pSdoComCon->m_uiTransSize = 0;
1267                             pSdoComCon->m_uiTransferredByte = 0;
1268                             // change state
1269                             pSdoComCon->m_SdoComState = kEplSdoComStateIdle;
1270                             // reset abort code
1271                             pSdoComCon->m_dwLastAbortCode = 0;
1272                             // d.k.: do not execute anything further on this command
1273                             break;
1274                         }
1275
1276                         // check if it is a write
1277                         if(pSdoComCon->m_SdoServiceType == kEplSdoServiceWriteByIndex)
1278                         {
1279                             // write data to OD
1280                             uiSize = AmiGetWordFromLe(&pAsySdoCom_p->m_le_wSegmentSize);
1281                             if(pSdoComCon->m_dwLastAbortCode == 0)
1282                             {
1283                                 EPL_MEMCPY(pSdoComCon->m_pData, &pAsySdoCom_p->m_le_abCommandData[0],uiSize);
1284                             }
1285                             // update counter
1286                             pSdoComCon->m_uiTransferredByte += uiSize;
1287                             pSdoComCon->m_uiTransSize -= uiSize;
1288
1289                             // update pointer
1290                             if(pSdoComCon->m_dwLastAbortCode == 0)
1291                             {
1292                                 (/*(BYTE*)*/pSdoComCon->m_pData) += uiSize;
1293                             }
1294
1295                             // check end of transfer
1296                             if((pAsySdoCom_p->m_le_bFlags & 0x30) == 0x30)
1297                             {   // transfer ready
1298                                 pSdoComCon->m_uiTransSize = 0;
1299
1300                                 if(pSdoComCon->m_dwLastAbortCode == 0)
1301                                 {
1302                                     // send response
1303                                     // send next frame
1304                                     EplSdoComServerSendFrameIntern(pSdoComCon,
1305                                                                         0,
1306                                                                         0,
1307                                                                         kEplSdoComSendTypeRes);
1308                                     // if all send -> back to idle
1309                                     if(pSdoComCon->m_uiTransSize == 0)
1310                                     {   // back to idle
1311                                         pSdoComCon->m_SdoComState = kEplSdoComStateIdle;
1312                                         // reset abort code
1313                                         pSdoComCon->m_dwLastAbortCode = 0;
1314                                     }
1315                                 }
1316                                 else
1317                                 {   // send dabort code
1318                                     // send abort
1319                                     pSdoComCon->m_pData = (BYTE*)&pSdoComCon->m_dwLastAbortCode;
1320                                     Ret = EplSdoComServerSendFrameIntern(pSdoComCon,
1321                                                                 0,
1322                                                                 0,
1323                                                                 kEplSdoComSendTypeAbort);
1324
1325                                     // reset abort code
1326                                     pSdoComCon->m_dwLastAbortCode = 0;
1327
1328                                 }
1329                             }
1330                             else
1331                             {
1332                                 // send acknowledge without any Command layer data
1333                                 Ret = EplSdoAsySeqSendData(pSdoComCon->m_SdoSeqConHdl,
1334                                                                         0,
1335                                                                         (tEplFrame*)NULL);
1336                             }
1337                         }
1338                     }
1339                     else
1340                     {   // this command layer handle is not responsible
1341                         // (wrong direction or wrong transaction ID)
1342                         Ret = kEplSdoComNotResponsible;
1343                         goto Exit;
1344                     }
1345                     break;
1346                 }
1347
1348                 // connection closed
1349                 case kEplSdoComConEventInitError:
1350                 case kEplSdoComConEventTimeout:
1351                 case kEplSdoComConEventConClosed:
1352                 {
1353                     Ret = EplSdoAsySeqDelCon(pSdoComCon->m_SdoSeqConHdl);
1354                     // clean control structure
1355                     EPL_MEMSET(pSdoComCon, 0x00, sizeof(tEplSdoComCon));
1356                     break;
1357                 }
1358
1359                 default:
1360                     // d.k. do nothing
1361                     break;
1362             }// end of switch(SdoComConEvent_p)
1363
1364             break;
1365         }
1366 #endif // endif of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
1367
1368
1369 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
1370         //-------------------------------------------------------------------------
1371         // SDO Client part
1372         // wait for finish of establishing connection
1373         case kEplSdoComStateClientWaitInit:
1374         {
1375
1376             // if connection handle is invalid reinit connection
1377             // d.k.: this will be done only on new events (i.e. InitTransfer)
1378             if((pSdoComCon->m_SdoSeqConHdl & ~EPL_SDO_SEQ_HANDLE_MASK) == EPL_SDO_SEQ_INVALID_HDL)
1379             {
1380                 // check kind of connection to reinit
1381                 // check protocol
1382                 switch(pSdoComCon->m_SdoProtType)
1383                 {
1384                     // udp
1385                     case kEplSdoTypeUdp:
1386                     {
1387                         // call connection int function of lower layer
1388                         Ret = EplSdoAsySeqInitCon(&pSdoComCon->m_SdoSeqConHdl,
1389                                     pSdoComCon->m_uiNodeId,
1390                                     kEplSdoTypeUdp);
1391                         if(Ret != kEplSuccessful)
1392                         {
1393                             goto Exit;
1394                         }
1395                         break;
1396                     }
1397
1398                     // Asend -> not supported
1399                     case kEplSdoTypeAsnd:
1400                     {
1401                         // call connection int function of lower layer
1402                         Ret = EplSdoAsySeqInitCon(&pSdoComCon->m_SdoSeqConHdl,
1403                                     pSdoComCon->m_uiNodeId,
1404                                     kEplSdoTypeAsnd);
1405                         if(Ret != kEplSuccessful)
1406                         {
1407                             goto Exit;
1408                         }
1409                         break;
1410                     }
1411
1412                     // Pdo -> not supported
1413                     case kEplSdoTypePdo:
1414                     default:
1415                     {
1416                         Ret = kEplSdoComUnsupportedProt;
1417                         goto Exit;
1418                     }
1419                 }// end of switch(m_ProtType_p)
1420                 // d.k.: reset transaction ID, because new sequence layer connection was initialized
1421                 // $$$ d.k. is this really necessary?
1422                 //pSdoComCon->m_bTransactionId = 0;
1423             }
1424
1425             // check events
1426             switch(SdoComConEvent_p)
1427             {
1428                 // connection established
1429                 case kEplSdoComConEventConEstablished:
1430                 {
1431                     //send first frame if needed
1432                     if((pSdoComCon->m_uiTransSize > 0)
1433                         &&(pSdoComCon->m_uiTargetIndex != 0))
1434                     {   // start SDO transfer
1435                         Ret = EplSdoComClientSend(pSdoComCon);
1436                         if(Ret != kEplSuccessful)
1437                         {
1438                             goto Exit;
1439                         }
1440
1441                         // check if segemted transfer
1442                         if(pSdoComCon->m_SdoTransType == kEplSdoTransSegmented)
1443                         {
1444                             pSdoComCon->m_SdoComState = kEplSdoComStateClientSegmTrans;
1445                             goto Exit;
1446                         }
1447                     }
1448                     // goto state kEplSdoComStateClientConnected
1449                     pSdoComCon->m_SdoComState = kEplSdoComStateClientConnected;
1450                     goto Exit;
1451                 }
1452
1453                 case kEplSdoComConEventSendFirst:
1454                 {
1455                     // infos for transfer already saved by function EplSdoComInitTransferByIndex
1456                     break;
1457                 }
1458
1459                 case kEplSdoComConEventConClosed:
1460                 case kEplSdoComConEventInitError:
1461                 case kEplSdoComConEventTimeout:
1462                 {
1463                     // close sequence layer handle
1464                     Ret = EplSdoAsySeqDelCon(pSdoComCon->m_SdoSeqConHdl);
1465                     pSdoComCon->m_SdoSeqConHdl |= EPL_SDO_SEQ_INVALID_HDL;
1466                     // call callback function
1467                     if (SdoComConEvent_p == kEplSdoComConEventTimeout)
1468                     {
1469                         pSdoComCon->m_dwLastAbortCode = EPL_SDOAC_TIME_OUT;
1470                     }
1471                     else
1472                     {
1473                         pSdoComCon->m_dwLastAbortCode = 0;
1474                     }
1475                     Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferLowerLayerAbort);
1476                     // d.k.: do not clean control structure
1477                     break;
1478                 }
1479
1480                 default:
1481                     // d.k. do nothing
1482                     break;
1483
1484             } // end of  switch(SdoComConEvent_p)
1485             break;
1486         }
1487
1488         // connected
1489         case kEplSdoComStateClientConnected:
1490         {
1491             // check events
1492             switch(SdoComConEvent_p)
1493             {
1494                 // send a frame
1495                 case kEplSdoComConEventSendFirst:
1496                 case kEplSdoComConEventAckReceived:
1497                 case kEplSdoComConEventFrameSended:
1498                 {
1499                     Ret = EplSdoComClientSend(pSdoComCon);
1500                     if(Ret != kEplSuccessful)
1501                     {
1502                         goto Exit;
1503                     }
1504
1505                     // check if read transfer finished
1506                     if((pSdoComCon->m_uiTransSize == 0)
1507                         && (pSdoComCon->m_uiTransferredByte != 0)
1508                         && (pSdoComCon->m_SdoServiceType == kEplSdoServiceReadByIndex))
1509                     {
1510                         // inc transaction id
1511                         pSdoComCon->m_bTransactionId++;
1512                         // call callback of application
1513                         pSdoComCon->m_dwLastAbortCode = 0;
1514                         Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferFinished);
1515
1516                         goto Exit;
1517                     }
1518
1519                     // check if segemted transfer
1520                     if(pSdoComCon->m_SdoTransType == kEplSdoTransSegmented)
1521                     {
1522                         pSdoComCon->m_SdoComState = kEplSdoComStateClientSegmTrans;
1523                         goto Exit;
1524                     }
1525                     break;
1526                 }
1527
1528                 // frame received
1529                 case kEplSdoComConEventRec:
1530                 {
1531                     // check if the frame is a SDO response and has the right transaction ID
1532                     bFlag = AmiGetByteFromLe(&pAsySdoCom_p->m_le_bFlags);
1533                     if (((bFlag & 0x80) != 0) && (AmiGetByteFromLe(&pAsySdoCom_p->m_le_bTransactionId) == pSdoComCon->m_bTransactionId))
1534                     {
1535                         // check if abort or not
1536                         if((bFlag & 0x40) != 0)
1537                         {
1538                             // send acknowledge without any Command layer data
1539                             Ret = EplSdoAsySeqSendData(pSdoComCon->m_SdoSeqConHdl,
1540                                                                     0,
1541                                                                     (tEplFrame*)NULL);
1542                             // inc transaction id
1543                             pSdoComCon->m_bTransactionId++;
1544                             // save abort code
1545                             pSdoComCon->m_dwLastAbortCode = AmiGetDwordFromLe(&pAsySdoCom_p->m_le_abCommandData[0]);
1546                             // call callback of application
1547                             Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferRxAborted);
1548
1549                             goto Exit;
1550                         }
1551                         else
1552                         {   // normal frame received
1553                             // check frame
1554                             Ret = EplSdoComClientProcessFrame(SdoComCon_p, pAsySdoCom_p);
1555
1556                             // check if transfer ready
1557                             if(pSdoComCon->m_uiTransSize == 0)
1558                             {
1559                                 // send acknowledge without any Command layer data
1560                                 Ret = EplSdoAsySeqSendData(pSdoComCon->m_SdoSeqConHdl,
1561                                                                         0,
1562                                                                         (tEplFrame*)NULL);
1563                                 // inc transaction id
1564                                 pSdoComCon->m_bTransactionId++;
1565                                 // call callback of application
1566                                 pSdoComCon->m_dwLastAbortCode = 0;
1567                                 Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferFinished);
1568
1569                                 goto Exit;
1570                             }
1571
1572                         }
1573                     }
1574                     else
1575                     {   // this command layer handle is not responsible
1576                         // (wrong direction or wrong transaction ID)
1577                         Ret = kEplSdoComNotResponsible;
1578                         goto Exit;
1579                     }
1580                     break;
1581                 }
1582
1583                 // connection closed event go back to kEplSdoComStateClientWaitInit
1584                 case kEplSdoComConEventConClosed:
1585                 {   // connection closed by communication partner
1586                     // close sequence layer handle
1587                     Ret = EplSdoAsySeqDelCon(pSdoComCon->m_SdoSeqConHdl);
1588                     // set handle to invalid and enter kEplSdoComStateClientWaitInit
1589                     pSdoComCon->m_SdoSeqConHdl |= EPL_SDO_SEQ_INVALID_HDL;
1590                     // change state
1591                     pSdoComCon->m_SdoComState = kEplSdoComStateClientWaitInit;
1592
1593                     // call callback of application
1594                     pSdoComCon->m_dwLastAbortCode = 0;
1595                     Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferLowerLayerAbort);
1596
1597                     goto Exit;
1598
1599                     break;
1600                 }
1601
1602                 // abort to send from higher layer
1603                 case kEplSdoComConEventAbort:
1604                 {
1605                     EplSdoComClientSendAbort(pSdoComCon,*((DWORD*)pSdoComCon->m_pData));
1606
1607                     // inc transaction id
1608                     pSdoComCon->m_bTransactionId++;
1609                     // call callback of application
1610                     pSdoComCon->m_dwLastAbortCode = *((DWORD*)pSdoComCon->m_pData);
1611                     Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferTxAborted);
1612
1613                     break;
1614                 }
1615
1616                 case kEplSdoComConEventInitError:
1617                 case kEplSdoComConEventTimeout:
1618                 {
1619                     // close sequence layer handle
1620                     Ret = EplSdoAsySeqDelCon(pSdoComCon->m_SdoSeqConHdl);
1621                     pSdoComCon->m_SdoSeqConHdl |= EPL_SDO_SEQ_INVALID_HDL;
1622                     // change state
1623                     pSdoComCon->m_SdoComState = kEplSdoComStateClientWaitInit;
1624                     // call callback of application
1625                     pSdoComCon->m_dwLastAbortCode = EPL_SDOAC_TIME_OUT;
1626                     Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferLowerLayerAbort);
1627
1628                 }
1629
1630                 default:
1631                     // d.k. do nothing
1632                     break;
1633
1634             } // end of switch(SdoComConEvent_p)
1635
1636             break;
1637         }
1638
1639         // process segmented transfer
1640         case kEplSdoComStateClientSegmTrans:
1641         {
1642             // check events
1643             switch(SdoComConEvent_p)
1644             {
1645                 // sned a frame
1646                 case kEplSdoComConEventSendFirst:
1647                 case kEplSdoComConEventAckReceived:
1648                 case kEplSdoComConEventFrameSended:
1649                 {
1650                     Ret = EplSdoComClientSend(pSdoComCon);
1651                     if(Ret != kEplSuccessful)
1652                     {
1653                         goto Exit;
1654                     }
1655
1656                     // check if read transfer finished
1657                     if((pSdoComCon->m_uiTransSize == 0)
1658                         && (pSdoComCon->m_SdoServiceType == kEplSdoServiceReadByIndex))
1659                     {
1660                         // inc transaction id
1661                         pSdoComCon->m_bTransactionId++;
1662                         // change state
1663                         pSdoComCon->m_SdoComState = kEplSdoComStateClientConnected;
1664                         // call callback of application
1665                         pSdoComCon->m_dwLastAbortCode = 0;
1666                         Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferFinished);
1667
1668                         goto Exit;
1669                     }
1670
1671                     break;
1672                 }
1673
1674                 // frame received
1675                 case kEplSdoComConEventRec:
1676                 {
1677                     // check if the frame is a response
1678                     bFlag = AmiGetByteFromLe(&pAsySdoCom_p->m_le_bFlags);
1679                     if (((bFlag & 0x80) != 0) && (AmiGetByteFromLe(&pAsySdoCom_p->m_le_bTransactionId) == pSdoComCon->m_bTransactionId))
1680                     {
1681                         // check if abort or not
1682                         if((bFlag & 0x40) != 0)
1683                         {
1684                             // send acknowledge without any Command layer data
1685                             Ret = EplSdoAsySeqSendData(pSdoComCon->m_SdoSeqConHdl,
1686                                                                     0,
1687                                                                     (tEplFrame*)NULL);
1688                             // inc transaction id
1689                             pSdoComCon->m_bTransactionId++;
1690                             // change state
1691                             pSdoComCon->m_SdoComState = kEplSdoComStateClientConnected;
1692                             // save abort code
1693                             pSdoComCon->m_dwLastAbortCode = AmiGetDwordFromLe(&pAsySdoCom_p->m_le_abCommandData[0]);
1694                             // call callback of application
1695                             Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferRxAborted);
1696
1697                             goto Exit;
1698                         }
1699                         else
1700                         {   // normal frame received
1701                             // check frame
1702                             Ret = EplSdoComClientProcessFrame(SdoComCon_p, pAsySdoCom_p);
1703
1704                             // check if transfer ready
1705                             if(pSdoComCon->m_uiTransSize == 0)
1706                             {
1707                                 // send acknowledge without any Command layer data
1708                                 Ret = EplSdoAsySeqSendData(pSdoComCon->m_SdoSeqConHdl,
1709                                                                         0,
1710                                                                         (tEplFrame*)NULL);
1711                                 // inc transaction id
1712                                 pSdoComCon->m_bTransactionId++;
1713                                 // change state
1714                                 pSdoComCon->m_SdoComState = kEplSdoComStateClientConnected;
1715                                 // call callback of application
1716                                 pSdoComCon->m_dwLastAbortCode = 0;
1717                                 Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferFinished);
1718
1719                             }
1720
1721                         }
1722                     }
1723                     break;
1724                 }
1725
1726                 // connection closed event go back to kEplSdoComStateClientWaitInit
1727                 case kEplSdoComConEventConClosed:
1728                 {   // connection closed by communication partner
1729                     // close sequence layer handle
1730                     Ret = EplSdoAsySeqDelCon(pSdoComCon->m_SdoSeqConHdl);
1731                     // set handle to invalid and enter kEplSdoComStateClientWaitInit
1732                     pSdoComCon->m_SdoSeqConHdl |= EPL_SDO_SEQ_INVALID_HDL;
1733                     // change state
1734                     pSdoComCon->m_SdoComState = kEplSdoComStateClientWaitInit;
1735                     // inc transaction id
1736                     pSdoComCon->m_bTransactionId++;
1737                     // call callback of application
1738                     pSdoComCon->m_dwLastAbortCode = 0;
1739                     Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferFinished);
1740
1741                     break;
1742                 }
1743
1744                 // abort to send from higher layer
1745                 case kEplSdoComConEventAbort:
1746                 {
1747                     EplSdoComClientSendAbort(pSdoComCon,*((DWORD*)pSdoComCon->m_pData));
1748
1749                     // inc transaction id
1750                     pSdoComCon->m_bTransactionId++;
1751                     // change state
1752                     pSdoComCon->m_SdoComState = kEplSdoComStateClientConnected;
1753                     // call callback of application
1754                     pSdoComCon->m_dwLastAbortCode = *((DWORD*)pSdoComCon->m_pData);
1755                     Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferTxAborted);
1756
1757                     break;
1758                 }
1759
1760                 case kEplSdoComConEventInitError:
1761                 case kEplSdoComConEventTimeout:
1762                 {
1763                     // close sequence layer handle
1764                     Ret = EplSdoAsySeqDelCon(pSdoComCon->m_SdoSeqConHdl);
1765                     pSdoComCon->m_SdoSeqConHdl |= EPL_SDO_SEQ_INVALID_HDL;
1766                     // change state
1767                     pSdoComCon->m_SdoComState = kEplSdoComStateClientWaitInit;
1768                     // call callback of application
1769                     pSdoComCon->m_dwLastAbortCode = EPL_SDOAC_TIME_OUT;
1770                     Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferLowerLayerAbort);
1771
1772                 }
1773
1774                 default:
1775                     // d.k. do nothing
1776                     break;
1777
1778             } // end of switch(SdoComConEvent_p)
1779
1780             break;
1781         }
1782 #endif // endo of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
1783
1784     }// end of switch(pSdoComCon->m_SdoComState)
1785
1786
1787
1788 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
1789 Exit:
1790 #endif
1791
1792 #if defined(WIN32) || defined(_WIN32)
1793     // leave critical section for process function
1794     EPL_DBGLVL_SDO_TRACE0("\n\tLeaveCriticalSection EplSdoComProcessIntern\n\n");
1795     LeaveCriticalSection(SdoComInstance_g.m_pCriticalSection);
1796
1797 #endif
1798
1799     return Ret;
1800
1801 }
1802
1803
1804 //---------------------------------------------------------------------------
1805 //
1806 // Function:        EplSdoComServerInitReadByIndex
1807 //
1808 // Description:    function start the processing of an read by index command
1809 //
1810 //
1811 //
1812 // Parameters:      pSdoComCon_p     = pointer to control structure of connection
1813 //                  pAsySdoCom_p     = pointer to received frame
1814 //
1815 // Returns:         tEplKernel  =  errorcode
1816 //
1817 //
1818 // State:
1819 //
1820 //---------------------------------------------------------------------------
1821 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
1822 static tEplKernel EplSdoComServerInitReadByIndex(tEplSdoComCon*     pSdoComCon_p,
1823                                          tEplAsySdoCom*     pAsySdoCom_p)
1824 {
1825 tEplKernel      Ret;
1826 unsigned int    uiIndex;
1827 unsigned int    uiSubindex;
1828 tEplObdSize     EntrySize;
1829 tEplObdAccess   AccessType;
1830 DWORD           dwAbortCode;
1831
1832     dwAbortCode = 0;
1833
1834     // a init of a read could not be a segmented transfer
1835     // -> no variable part of header
1836
1837     // get index and subindex
1838     uiIndex = AmiGetWordFromLe(&pAsySdoCom_p->m_le_abCommandData[0]);
1839     uiSubindex = AmiGetByteFromLe(&pAsySdoCom_p->m_le_abCommandData[2]);
1840
1841     // check accesstype of entry
1842     // existens of entry
1843 //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
1844     Ret = EplObduGetAccessType(uiIndex, uiSubindex, &AccessType);
1845 /*#else
1846     Ret = kEplObdSubindexNotExist;
1847     AccessType = 0;
1848 #endif*/
1849     if(Ret == kEplObdSubindexNotExist)
1850     {   // subentry doesn't exist
1851         dwAbortCode = EPL_SDOAC_SUB_INDEX_NOT_EXIST;
1852         // send abort
1853         pSdoComCon_p->m_pData = (BYTE*)&dwAbortCode;
1854         Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
1855                                     uiIndex,
1856                                     uiSubindex,
1857                                     kEplSdoComSendTypeAbort);
1858         goto Exit;
1859     }
1860     else if(Ret != kEplSuccessful)
1861     {   // entry doesn't exist
1862         dwAbortCode = EPL_SDOAC_OBJECT_NOT_EXIST;
1863         // send abort
1864         pSdoComCon_p->m_pData = (BYTE*)&dwAbortCode;
1865         Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
1866                                     uiIndex,
1867                                     uiSubindex,
1868                                     kEplSdoComSendTypeAbort);
1869         goto Exit;
1870     }
1871
1872     // compare accesstype must be read or const
1873     if(((AccessType & kEplObdAccRead) == 0)
1874         && ((AccessType & kEplObdAccConst) == 0))
1875     {
1876
1877         if((AccessType & kEplObdAccWrite) != 0)
1878         {
1879             // entry read a write only object
1880             dwAbortCode = EPL_SDOAC_READ_TO_WRITE_ONLY_OBJ;
1881         }
1882         else
1883         {
1884             dwAbortCode = EPL_SDOAC_UNSUPPORTED_ACCESS;
1885         }
1886         // send abort
1887         pSdoComCon_p->m_pData = (BYTE*)&dwAbortCode;
1888         Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
1889                                     uiIndex,
1890                                     uiSubindex,
1891                                     kEplSdoComSendTypeAbort);
1892         goto Exit;
1893     }
1894
1895     // save service
1896     pSdoComCon_p->m_SdoServiceType = kEplSdoServiceReadByIndex;
1897
1898     // get size of object to see iof segmented or expedited transfer
1899 //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
1900     EntrySize = EplObduGetDataSize(uiIndex, uiSubindex);
1901 /*#else
1902     EntrySize = 0;
1903 #endif*/
1904     if(EntrySize > EPL_SDO_MAX_PAYLOAD)
1905     {   // segmented transfer
1906         pSdoComCon_p->m_SdoTransType = kEplSdoTransSegmented;
1907         // get pointer to object-entry data
1908 //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
1909         pSdoComCon_p->m_pData = EplObduGetObjectDataPtr(uiIndex, uiSubindex);
1910 //#endif
1911     }
1912     else
1913     {   // expedited transfer
1914         pSdoComCon_p->m_SdoTransType = kEplSdoTransExpedited;
1915     }
1916
1917     pSdoComCon_p->m_uiTransSize = EntrySize;
1918     pSdoComCon_p->m_uiTransferredByte = 0;
1919
1920     Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
1921                                     uiIndex,
1922                                     uiSubindex,
1923                                     kEplSdoComSendTypeRes);
1924     if(Ret != kEplSuccessful)
1925     {
1926         // error -> abort
1927         dwAbortCode = EPL_SDOAC_GENERAL_ERROR;
1928         // send abort
1929         pSdoComCon_p->m_pData = (BYTE*)&dwAbortCode;
1930         Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
1931                                     uiIndex,
1932                                     uiSubindex,
1933                                     kEplSdoComSendTypeAbort);
1934         goto Exit;
1935     }
1936
1937 Exit:
1938     return Ret;
1939 }
1940 #endif
1941
1942 //---------------------------------------------------------------------------
1943 //
1944 // Function:        EplSdoComServerSendFrameIntern();
1945 //
1946 // Description:    function creats and send a frame for server
1947 //
1948 //
1949 //
1950 // Parameters:      pSdoComCon_p     = pointer to control structure of connection
1951 //                  uiIndex_p        = index to send if expedited transfer else 0
1952 //                  uiSubIndex_p     = subindex to send if expedited transfer else 0
1953 //                  SendType_p       = to of frame to send
1954 //
1955 // Returns:         tEplKernel  =  errorcode
1956 //
1957 //
1958 // State:
1959 //
1960 //---------------------------------------------------------------------------
1961 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
1962 static tEplKernel EplSdoComServerSendFrameIntern(tEplSdoComCon*     pSdoComCon_p,
1963                                            unsigned int       uiIndex_p,
1964                                            unsigned int       uiSubIndex_p,
1965                                            tEplSdoComSendType SendType_p)
1966 {
1967 tEplKernel      Ret;
1968 BYTE            abFrame[EPL_MAX_SDO_FRAME_SIZE];
1969 tEplFrame*      pFrame;
1970 tEplAsySdoCom*  pCommandFrame;
1971 unsigned int    uiSizeOfFrame;
1972 BYTE            bFlag;
1973
1974     Ret = kEplSuccessful;
1975
1976     pFrame = (tEplFrame*)&abFrame[0];
1977
1978     EPL_MEMSET(&abFrame[0], 0x00, sizeof(abFrame));
1979
1980     // build generic part of frame
1981     // get pointer to command layerpart of frame
1982     pCommandFrame = &pFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame.m_le_abSdoSeqPayload;
1983     AmiSetByteToLe(&pCommandFrame->m_le_bCommandId, pSdoComCon_p->m_SdoServiceType);
1984     AmiSetByteToLe(&pCommandFrame->m_le_bTransactionId, pSdoComCon_p->m_bTransactionId);
1985
1986     // set size to header size
1987     uiSizeOfFrame = 8;
1988
1989     // check SendType
1990     switch(SendType_p)
1991     {
1992         // requestframe to send
1993         case kEplSdoComSendTypeReq:
1994         {
1995             // nothing to do for server
1996             //-> error
1997             Ret = kEplSdoComInvalidSendType;
1998             break;
1999         }
2000
2001         // response without data to send
2002         case kEplSdoComSendTypeAckRes:
2003         {
2004             // set response flag
2005             AmiSetByteToLe(&pCommandFrame->m_le_bFlags,  0x80);
2006
2007             // send frame
2008             Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl,
2009                                             uiSizeOfFrame,
2010                                             pFrame);
2011
2012             break;
2013         }
2014
2015         // responsframe to send
2016         case kEplSdoComSendTypeRes:
2017         {
2018             // set response flag
2019             bFlag = AmiGetByteFromLe( &pCommandFrame->m_le_bFlags);
2020             bFlag |= 0x80;
2021             AmiSetByteToLe(&pCommandFrame->m_le_bFlags,  bFlag);
2022
2023             // check type of resonse
2024             if(pSdoComCon_p->m_SdoTransType == kEplSdoTransExpedited)
2025             {   // Expedited transfer
2026                 // copy data in frame
2027 //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
2028                 Ret = EplObduReadEntryToLe(uiIndex_p,
2029                                         uiSubIndex_p,
2030                                         &pCommandFrame->m_le_abCommandData[0],
2031                                         (tEplObdSize*)&pSdoComCon_p->m_uiTransSize);
2032                 if(Ret != kEplSuccessful)
2033                 {
2034                     goto Exit;
2035                 }
2036 //#endif
2037
2038                 // set size of frame
2039                 AmiSetWordToLe(&pCommandFrame->m_le_wSegmentSize, (WORD) pSdoComCon_p->m_uiTransSize);
2040
2041                 // correct byte-counter
2042                 uiSizeOfFrame += pSdoComCon_p->m_uiTransSize;
2043                 pSdoComCon_p->m_uiTransferredByte += pSdoComCon_p->m_uiTransSize;
2044                 pSdoComCon_p->m_uiTransSize = 0;
2045
2046
2047                 // send frame
2048                 uiSizeOfFrame += pSdoComCon_p->m_uiTransSize;
2049                 Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl,
2050                                             uiSizeOfFrame,
2051                                             pFrame);
2052             }
2053             else if(pSdoComCon_p->m_SdoTransType == kEplSdoTransSegmented)
2054             {   // segmented transfer
2055                 // distinguish between init, segment and complete
2056                 if(pSdoComCon_p->m_uiTransferredByte == 0)
2057                 {   // init
2058                     // set init flag
2059                     bFlag = AmiGetByteFromLe( &pCommandFrame->m_le_bFlags);
2060                     bFlag |= 0x10;
2061                     AmiSetByteToLe(&pCommandFrame->m_le_bFlags,  bFlag);
2062                     // init variable header
2063                     AmiSetDwordToLe(&pCommandFrame->m_le_abCommandData[0],pSdoComCon_p->m_uiTransSize);
2064                     // copy data in frame
2065                     EPL_MEMCPY(&pCommandFrame->m_le_abCommandData[4],pSdoComCon_p->m_pData, (EPL_SDO_MAX_PAYLOAD-4));
2066
2067                     // correct byte-counter
2068                     pSdoComCon_p->m_uiTransSize -= (EPL_SDO_MAX_PAYLOAD-4);
2069                     pSdoComCon_p->m_uiTransferredByte += (EPL_SDO_MAX_PAYLOAD-4);
2070                     // move data pointer
2071                     pSdoComCon_p->m_pData +=(EPL_SDO_MAX_PAYLOAD-4);
2072
2073                     // set segment size
2074                     AmiSetWordToLe(&pCommandFrame->m_le_wSegmentSize,(EPL_SDO_MAX_PAYLOAD-4));
2075
2076                     // send frame
2077                     uiSizeOfFrame += EPL_SDO_MAX_PAYLOAD;
2078                     Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl,
2079                                                 uiSizeOfFrame,
2080                                                 pFrame);
2081
2082                 }
2083                 else if((pSdoComCon_p->m_uiTransferredByte > 0)
2084                     &&(pSdoComCon_p->m_uiTransSize > EPL_SDO_MAX_PAYLOAD))
2085                 {   // segment
2086                     // set segment flag
2087                     bFlag = AmiGetByteFromLe( &pCommandFrame->m_le_bFlags);
2088                     bFlag |= 0x20;
2089                     AmiSetByteToLe(&pCommandFrame->m_le_bFlags,  bFlag);
2090
2091                     // copy data in frame
2092                     EPL_MEMCPY(&pCommandFrame->m_le_abCommandData[0],pSdoComCon_p->m_pData, EPL_SDO_MAX_PAYLOAD);
2093
2094                     // correct byte-counter
2095                     pSdoComCon_p->m_uiTransSize -= EPL_SDO_MAX_PAYLOAD;
2096                     pSdoComCon_p->m_uiTransferredByte += EPL_SDO_MAX_PAYLOAD;
2097                     // move data pointer
2098                     pSdoComCon_p->m_pData +=EPL_SDO_MAX_PAYLOAD;
2099
2100                     // set segment size
2101                     AmiSetWordToLe(&pCommandFrame->m_le_wSegmentSize,EPL_SDO_MAX_PAYLOAD);
2102
2103                     // send frame
2104                     uiSizeOfFrame += EPL_SDO_MAX_PAYLOAD;
2105                     Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl,
2106                                                 uiSizeOfFrame,
2107                                                 pFrame);
2108                 }
2109                 else
2110                 {
2111                     if((pSdoComCon_p->m_uiTransSize == 0)
2112                         && (pSdoComCon_p->m_SdoServiceType != kEplSdoServiceWriteByIndex))
2113                     {
2114                         goto Exit;
2115                     }
2116                     // complete
2117                     // set segment complete flag
2118                     bFlag = AmiGetByteFromLe( &pCommandFrame->m_le_bFlags);
2119                     bFlag |= 0x30;
2120                     AmiSetByteToLe(&pCommandFrame->m_le_bFlags,  bFlag);
2121
2122                     // copy data in frame
2123                     EPL_MEMCPY(&pCommandFrame->m_le_abCommandData[0],pSdoComCon_p->m_pData, pSdoComCon_p->m_uiTransSize);
2124
2125                     // correct byte-counter
2126                     pSdoComCon_p->m_uiTransferredByte += pSdoComCon_p->m_uiTransSize;
2127
2128
2129                     // move data pointer
2130                     pSdoComCon_p->m_pData +=pSdoComCon_p->m_uiTransSize;
2131
2132                     // set segment size
2133                     AmiSetWordToLe(&pCommandFrame->m_le_wSegmentSize, (WORD) pSdoComCon_p->m_uiTransSize);
2134
2135                     // send frame
2136                     uiSizeOfFrame += pSdoComCon_p->m_uiTransSize;
2137                     pSdoComCon_p->m_uiTransSize = 0;
2138                     Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl,
2139                                                 uiSizeOfFrame,
2140                                                 pFrame);
2141                 }
2142
2143             }
2144             break;
2145         }
2146         // abort to send
2147         case kEplSdoComSendTypeAbort:
2148         {
2149             // set response and abort flag
2150             bFlag = AmiGetByteFromLe( &pCommandFrame->m_le_bFlags);
2151             bFlag |= 0xC0;
2152             AmiSetByteToLe(&pCommandFrame->m_le_bFlags,  bFlag);
2153
2154             // copy abortcode to frame
2155             AmiSetDwordToLe(&pCommandFrame->m_le_abCommandData[0], *((DWORD*)pSdoComCon_p->m_pData));
2156
2157             // set size of segment
2158             AmiSetWordToLe(&pCommandFrame->m_le_wSegmentSize, sizeof(DWORD));
2159
2160             // update counter
2161             pSdoComCon_p->m_uiTransferredByte = sizeof(DWORD);
2162             pSdoComCon_p->m_uiTransSize = 0;
2163
2164             // calc framesize
2165             uiSizeOfFrame += sizeof(DWORD);
2166             Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl,
2167                                                 uiSizeOfFrame,
2168                                                 pFrame);
2169             break;
2170         }
2171     } // end of switch(SendType_p)
2172
2173 Exit:
2174     return Ret;
2175 }
2176 #endif
2177 //---------------------------------------------------------------------------
2178 //
2179 // Function:        EplSdoComServerInitWriteByIndex
2180 //
2181 // Description:    function start the processing of an write by index command
2182 //
2183 //
2184 //
2185 // Parameters:      pSdoComCon_p     = pointer to control structure of connection
2186 //                  pAsySdoCom_p     = pointer to received frame
2187 //
2188 // Returns:         tEplKernel  =  errorcode
2189 //
2190 //
2191 // State:
2192 //
2193 //---------------------------------------------------------------------------
2194 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
2195 static tEplKernel EplSdoComServerInitWriteByIndex(tEplSdoComCon*     pSdoComCon_p,
2196                                          tEplAsySdoCom*     pAsySdoCom_p)
2197 {
2198 tEplKernel  Ret = kEplSuccessful;
2199 unsigned int    uiIndex;
2200 unsigned int    uiSubindex;
2201 unsigned int    uiBytesToTransfer;
2202 tEplObdSize     EntrySize;
2203 tEplObdAccess   AccessType;
2204 DWORD           dwAbortCode;
2205 BYTE*           pbSrcData;
2206
2207     dwAbortCode = 0;
2208
2209     // a init of a write
2210     // -> variable part of header possible
2211
2212     // check if expedited or segmented transfer
2213     if ((pAsySdoCom_p->m_le_bFlags & 0x30) == 0x10)
2214     {   // initiate segmented transfer
2215         pSdoComCon_p->m_SdoTransType = kEplSdoTransSegmented;
2216         // get index and subindex
2217         uiIndex = AmiGetWordFromLe(&pAsySdoCom_p->m_le_abCommandData[4]);
2218         uiSubindex = AmiGetByteFromLe(&pAsySdoCom_p->m_le_abCommandData[6]);
2219         // get source-pointer for copy
2220         pbSrcData = &pAsySdoCom_p->m_le_abCommandData[8];
2221         // save size
2222         pSdoComCon_p->m_uiTransSize = AmiGetDwordFromLe(&pAsySdoCom_p->m_le_abCommandData[0]);
2223
2224     }
2225     else if ((pAsySdoCom_p->m_le_bFlags & 0x30) == 0x00)
2226     {   // expedited transfer
2227         pSdoComCon_p->m_SdoTransType = kEplSdoTransExpedited;
2228         // get index and subindex
2229         uiIndex = AmiGetWordFromLe(&pAsySdoCom_p->m_le_abCommandData[0]);
2230         uiSubindex = AmiGetByteFromLe(&pAsySdoCom_p->m_le_abCommandData[2]);
2231         // get source-pointer for copy
2232         pbSrcData = &pAsySdoCom_p->m_le_abCommandData[4];
2233         // save size
2234         pSdoComCon_p->m_uiTransSize = AmiGetWordFromLe(&pAsySdoCom_p->m_le_wSegmentSize);
2235         // subtract header
2236         pSdoComCon_p->m_uiTransSize -= 4;
2237
2238     }
2239     else
2240     {
2241         // just ignore any other transfer type
2242         goto Exit;
2243     }
2244
2245     // check accesstype of entry
2246     // existens of entry
2247 //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
2248     Ret = EplObduGetAccessType(uiIndex, uiSubindex, &AccessType);
2249 /*#else
2250     Ret = kEplObdSubindexNotExist;
2251     AccessType = 0;
2252 #endif*/
2253     if (Ret == kEplObdSubindexNotExist)
2254     {   // subentry doesn't exist
2255         pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_SUB_INDEX_NOT_EXIST;
2256         // send abort
2257         // d.k. This is wrong: k.t. not needed send abort on end of write
2258         /*pSdoComCon_p->m_pData = (BYTE*)pSdoComCon_p->m_dwLastAbortCode;
2259         Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
2260                                     uiIndex,
2261                                     uiSubindex,
2262                                     kEplSdoComSendTypeAbort);*/
2263         goto Abort;
2264     }
2265     else if(Ret != kEplSuccessful)
2266     {   // entry doesn't exist
2267         pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_OBJECT_NOT_EXIST;
2268         // send abort
2269         // d.k. This is wrong: k.t. not needed send abort on end of write
2270         /*
2271         pSdoComCon_p->m_pData = (BYTE*)&dwAbortCode;
2272         Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
2273                                     uiIndex,
2274                                     uiSubindex,
2275                                     kEplSdoComSendTypeAbort);*/
2276         goto Abort;
2277     }
2278
2279     // compare accesstype must be read
2280     if((AccessType & kEplObdAccWrite) == 0)
2281     {
2282
2283         if((AccessType & kEplObdAccRead) != 0)
2284         {
2285             // entry write a read only object
2286             pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_WRITE_TO_READ_ONLY_OBJ;
2287         }
2288         else
2289         {
2290             pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_UNSUPPORTED_ACCESS;
2291         }
2292         // send abort
2293         // d.k. This is wrong: k.t. not needed send abort on end of write
2294         /*pSdoComCon_p->m_pData = (BYTE*)&dwAbortCode;
2295         Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
2296                                     uiIndex,
2297                                     uiSubindex,
2298                                     kEplSdoComSendTypeAbort);*/
2299         goto Abort;
2300     }
2301
2302     // save service
2303     pSdoComCon_p->m_SdoServiceType = kEplSdoServiceWriteByIndex;
2304
2305     pSdoComCon_p->m_uiTransferredByte = 0;
2306
2307     // write data to OD
2308     if(pSdoComCon_p->m_SdoTransType == kEplSdoTransExpedited)
2309     {   // expedited transfer
2310         // size checking is done by EplObduWriteEntryFromLe()
2311
2312 //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
2313         Ret = EplObduWriteEntryFromLe(uiIndex,
2314                                     uiSubindex,
2315                                     pbSrcData,
2316                                     pSdoComCon_p->m_uiTransSize);
2317         switch (Ret)
2318         {
2319             case kEplSuccessful:
2320             {
2321                 break;
2322             }
2323
2324             case kEplObdAccessViolation:
2325             {
2326                 pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_UNSUPPORTED_ACCESS;
2327                 // send abort
2328                 goto Abort;
2329             }
2330
2331             case kEplObdValueLengthError:
2332             {
2333                 pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_DATA_TYPE_LENGTH_NOT_MATCH;
2334                 // send abort
2335                 goto Abort;
2336             }
2337
2338             case kEplObdValueTooHigh:
2339             {
2340                 pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_VALUE_RANGE_TOO_HIGH;
2341                 // send abort
2342                 goto Abort;
2343             }
2344
2345             case kEplObdValueTooLow:
2346             {
2347                 pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_VALUE_RANGE_TOO_LOW;
2348                 // send abort
2349                 goto Abort;
2350             }
2351
2352             default:
2353             {
2354                 pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_GENERAL_ERROR;
2355                 // send abort
2356                 goto Abort;
2357             }
2358         }
2359 //#endif
2360         // send command acknowledge
2361         Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
2362                                         0,
2363                                         0,
2364                                         kEplSdoComSendTypeAckRes);
2365
2366         pSdoComCon_p->m_uiTransSize = 0;
2367         goto Exit;
2368     }
2369     else
2370     {
2371         // get size of the object to check if it fits
2372         // because we directly write to the destination memory
2373         // d.k. no one calls the user OD callback function
2374
2375     //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
2376         EntrySize = EplObduGetDataSize(uiIndex, uiSubindex);
2377     /*#else
2378         EntrySize = 0;
2379     #endif*/
2380         if(EntrySize < pSdoComCon_p->m_uiTransSize)
2381         {   // parameter too big
2382             pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_DATA_TYPE_LENGTH_TOO_HIGH;
2383             // send abort
2384             // d.k. This is wrong: k.t. not needed send abort on end of write
2385             /*pSdoComCon_p->m_pData = (BYTE*)&dwAbortCode;
2386             Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
2387                                         uiIndex,
2388                                         uiSubindex,
2389                                         kEplSdoComSendTypeAbort);*/
2390             goto Abort;
2391         }
2392
2393         uiBytesToTransfer = AmiGetWordFromLe(&pAsySdoCom_p->m_le_wSegmentSize);
2394         // eleminate header (Command header (8) + variable part (4) + Command header (4))
2395         uiBytesToTransfer -= 16;
2396         // get pointer to object entry
2397 //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
2398         pSdoComCon_p->m_pData = EplObduGetObjectDataPtr(uiIndex,
2399                                                         uiSubindex);
2400 //#endif
2401         if(pSdoComCon_p->m_pData == NULL)
2402         {
2403             pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_GENERAL_ERROR;
2404             // send abort
2405             // d.k. This is wrong: k.t. not needed send abort on end of write
2406 /*            pSdoComCon_p->m_pData = (BYTE*)&pSdoComCon_p->m_dwLastAbortCode;
2407             Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
2408                                         uiIndex,
2409                                         uiSubindex,
2410                                         kEplSdoComSendTypeAbort);*/
2411             goto Abort;
2412         }
2413
2414         // copy data
2415         EPL_MEMCPY(pSdoComCon_p->m_pData, pbSrcData, uiBytesToTransfer);
2416
2417         // update internal counter
2418         pSdoComCon_p->m_uiTransferredByte = uiBytesToTransfer;
2419         pSdoComCon_p->m_uiTransSize -= uiBytesToTransfer;
2420
2421         // update target pointer
2422         (/*(BYTE*)*/pSdoComCon_p->m_pData) += uiBytesToTransfer;
2423
2424         // send acknowledge without any Command layer data
2425         Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl,
2426                                                 0,
2427                                                 (tEplFrame*)NULL);
2428         goto Exit;
2429     }
2430
2431 Abort:
2432     if(pSdoComCon_p->m_dwLastAbortCode != 0)
2433     {
2434         // send abort
2435         pSdoComCon_p->m_pData = (BYTE*)&pSdoComCon_p->m_dwLastAbortCode;
2436         Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
2437                                     uiIndex,
2438                                     uiSubindex,
2439                                     kEplSdoComSendTypeAbort);
2440
2441         // reset abort code
2442         pSdoComCon_p->m_dwLastAbortCode = 0;
2443         pSdoComCon_p->m_uiTransSize = 0;
2444         goto Exit;
2445     }
2446
2447 Exit:
2448     return Ret;
2449 }
2450 #endif
2451
2452 //---------------------------------------------------------------------------
2453 //
2454 // Function:        EplSdoComClientSend
2455 //
2456 // Description:    function starts an sdo transfer an send all further frames
2457 //
2458 //
2459 //
2460 // Parameters:      pSdoComCon_p     = pointer to control structure of connection
2461 //
2462 // Returns:         tEplKernel  =  errorcode
2463 //
2464 //
2465 // State:
2466 //
2467 //---------------------------------------------------------------------------
2468 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
2469 static tEplKernel EplSdoComClientSend(tEplSdoComCon* pSdoComCon_p)
2470 {
2471 tEplKernel      Ret;
2472 BYTE            abFrame[EPL_MAX_SDO_FRAME_SIZE];
2473 tEplFrame*      pFrame;
2474 tEplAsySdoCom*  pCommandFrame;
2475 unsigned int    uiSizeOfFrame;
2476 BYTE            bFlags;
2477 BYTE*           pbPayload;
2478
2479     Ret = kEplSuccessful;
2480
2481     pFrame = (tEplFrame*)&abFrame[0];
2482
2483     EPL_MEMSET(&abFrame[0], 0x00, sizeof(abFrame));
2484
2485     // build generic part of frame
2486     // get pointer to command layerpart of frame
2487     pCommandFrame = &pFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame.m_le_abSdoSeqPayload;
2488     AmiSetByteToLe( &pCommandFrame->m_le_bCommandId, pSdoComCon_p->m_SdoServiceType);
2489     AmiSetByteToLe( &pCommandFrame->m_le_bTransactionId, pSdoComCon_p->m_bTransactionId);
2490
2491     // set size constant part of header
2492     uiSizeOfFrame = 8;
2493
2494     // check if first frame to send -> command header needed
2495     if (pSdoComCon_p->m_uiTransSize > 0)
2496     {
2497         if (pSdoComCon_p->m_uiTransferredByte == 0)
2498         {   // start SDO transfer
2499             // check if segmented or expedited transfer
2500             // only for write commands
2501             switch(pSdoComCon_p->m_SdoServiceType)
2502             {
2503                 case kEplSdoServiceReadByIndex:
2504                 {   // first frame of read access always expedited
2505                     pSdoComCon_p->m_SdoTransType = kEplSdoTransExpedited;
2506                     pbPayload = &pCommandFrame->m_le_abCommandData[0];
2507                     // fill rest of header
2508                     AmiSetWordToLe( &pCommandFrame->m_le_wSegmentSize, 4);
2509
2510                     // create command header
2511                     AmiSetWordToLe(pbPayload, (WORD)pSdoComCon_p->m_uiTargetIndex);
2512                     pbPayload += 2;
2513                     AmiSetByteToLe(pbPayload, (BYTE)pSdoComCon_p->m_uiTargetSubIndex);
2514                     // calc size
2515                     uiSizeOfFrame += 4;
2516
2517                     // set pSdoComCon_p->m_uiTransferredByte to one
2518                     pSdoComCon_p->m_uiTransferredByte = 1;
2519                     break;
2520                 }
2521
2522                 case kEplSdoServiceWriteByIndex:
2523                 {
2524                     if(pSdoComCon_p->m_uiTransSize > EPL_SDO_MAX_PAYLOAD )
2525                     {   // segmented transfer
2526                         // -> variable part of header needed
2527                         // save that transfer is segmented
2528                         pSdoComCon_p->m_SdoTransType = kEplSdoTransSegmented;
2529                         // fill variable part of header
2530                         AmiSetDwordToLe( &pCommandFrame->m_le_abCommandData[0], pSdoComCon_p->m_uiTransSize);
2531                         // set pointer to real payload
2532                         pbPayload = &pCommandFrame->m_le_abCommandData[4];
2533                         // fill rest of header
2534                         AmiSetWordToLe( &pCommandFrame->m_le_wSegmentSize, EPL_SDO_MAX_PAYLOAD);
2535                         bFlags = 0x10;
2536                         AmiSetByteToLe( &pCommandFrame->m_le_bFlags, bFlags);
2537                         // create command header
2538                         AmiSetWordToLe(pbPayload, (WORD) pSdoComCon_p->m_uiTargetIndex);
2539                         pbPayload += 2;
2540                         AmiSetByteToLe(pbPayload, (BYTE)pSdoComCon_p->m_uiTargetSubIndex);
2541                         // on byte for reserved
2542                         pbPayload += 2;
2543                         // calc size
2544                         uiSizeOfFrame += EPL_SDO_MAX_PAYLOAD;
2545
2546                         // copy payload
2547                         EPL_MEMCPY( pbPayload,pSdoComCon_p->m_pData,  (EPL_SDO_MAX_PAYLOAD - 8));
2548                         pSdoComCon_p->m_pData += (EPL_SDO_MAX_PAYLOAD - 8);
2549                         // correct intern counter
2550                         pSdoComCon_p->m_uiTransSize -= (EPL_SDO_MAX_PAYLOAD - 8);
2551                         pSdoComCon_p->m_uiTransferredByte = (EPL_SDO_MAX_PAYLOAD - 8);
2552
2553                     }
2554                     else
2555                     {   // expedited trandsfer
2556                         // save that transfer is expedited
2557                         pSdoComCon_p->m_SdoTransType = kEplSdoTransExpedited;
2558                         pbPayload = &pCommandFrame->m_le_abCommandData[0];
2559
2560                         // create command header
2561                         AmiSetWordToLe(pbPayload, (WORD) pSdoComCon_p->m_uiTargetIndex);
2562                         pbPayload += 2;
2563                         AmiSetByteToLe(pbPayload, (BYTE)pSdoComCon_p->m_uiTargetSubIndex);
2564                         // + 2 -> one byte for subindex and one byte reserved
2565                         pbPayload += 2;
2566                         // copy data
2567                         EPL_MEMCPY( pbPayload,pSdoComCon_p->m_pData,  pSdoComCon_p->m_uiTransSize);
2568                         // calc size
2569                         uiSizeOfFrame += (4 + pSdoComCon_p->m_uiTransSize);
2570                         // fill rest of header
2571                         AmiSetWordToLe( &pCommandFrame->m_le_wSegmentSize, (WORD) (4 + pSdoComCon_p->m_uiTransSize));
2572
2573                         pSdoComCon_p->m_uiTransferredByte = pSdoComCon_p->m_uiTransSize;
2574                         pSdoComCon_p->m_uiTransSize = 0;
2575                     }
2576                     break;
2577                 }
2578
2579                 case kEplSdoServiceNIL:
2580                 default:
2581                     // invalid service requested
2582                     Ret = kEplSdoComInvalidServiceType;
2583                     goto Exit;
2584             } // end of switch(pSdoComCon_p->m_SdoServiceType)
2585         }
2586         else // (pSdoComCon_p->m_uiTransferredByte > 0)
2587         {   // continue SDO transfer
2588             switch(pSdoComCon_p->m_SdoServiceType)
2589             {
2590                 // for expedited read is nothing to do
2591                 // -> server sends data
2592
2593                 case kEplSdoServiceWriteByIndex:
2594                 {   // send next frame
2595                     if(pSdoComCon_p->m_SdoTransType == kEplSdoTransSegmented)
2596                     {
2597                         if(pSdoComCon_p->m_uiTransSize > EPL_SDO_MAX_PAYLOAD)
2598                         {   // next segment
2599                             pbPayload = &pCommandFrame->m_le_abCommandData[0];
2600                             // fill rest of header
2601                             AmiSetWordToLe( &pCommandFrame->m_le_wSegmentSize, EPL_SDO_MAX_PAYLOAD);
2602                             bFlags = 0x20;
2603                             AmiSetByteToLe( &pCommandFrame->m_le_bFlags, bFlags);
2604                             // copy data
2605                             EPL_MEMCPY( pbPayload,pSdoComCon_p->m_pData,  EPL_SDO_MAX_PAYLOAD);
2606                             pSdoComCon_p->m_pData += EPL_SDO_MAX_PAYLOAD;
2607                             // correct intern counter
2608                             pSdoComCon_p->m_uiTransSize -= EPL_SDO_MAX_PAYLOAD;
2609                             pSdoComCon_p->m_uiTransferredByte = EPL_SDO_MAX_PAYLOAD;
2610                             // calc size
2611                             uiSizeOfFrame += EPL_SDO_MAX_PAYLOAD;
2612
2613
2614                         }
2615                         else
2616                         {   // end of transfer
2617                             pbPayload = &pCommandFrame->m_le_abCommandData[0];
2618                             // fill rest of header
2619                             AmiSetWordToLe( &pCommandFrame->m_le_wSegmentSize, (WORD) pSdoComCon_p->m_uiTransSize);
2620                             bFlags = 0x30;
2621                             AmiSetByteToLe( &pCommandFrame->m_le_bFlags, bFlags);
2622                             // copy data
2623                             EPL_MEMCPY( pbPayload,pSdoComCon_p->m_pData,  pSdoComCon_p->m_uiTransSize);
2624                             pSdoComCon_p->m_pData += pSdoComCon_p->m_uiTransSize;
2625                             // calc size
2626                             uiSizeOfFrame += pSdoComCon_p->m_uiTransSize;
2627                             // correct intern counter
2628                             pSdoComCon_p->m_uiTransSize = 0;
2629                             pSdoComCon_p->m_uiTransferredByte = pSdoComCon_p->m_uiTransSize;
2630
2631                         }
2632                     }
2633                     else
2634                     {
2635                         goto Exit;
2636                     }
2637                     break;
2638                 }
2639                 default:
2640                 {
2641                     goto Exit;
2642                 }
2643             } // end of switch(pSdoComCon_p->m_SdoServiceType)
2644         }
2645     }
2646     else
2647     {
2648         goto Exit;
2649     }
2650
2651
2652     // call send function of lower layer
2653     switch(pSdoComCon_p->m_SdoProtType)
2654     {
2655         case kEplSdoTypeAsnd:
2656         case kEplSdoTypeUdp:
2657         {
2658             Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl,
2659                                         uiSizeOfFrame,
2660                                         pFrame);
2661             break;
2662         }
2663
2664         default:
2665         {
2666             Ret = kEplSdoComUnsupportedProt;
2667         }
2668     } // end of switch(pSdoComCon_p->m_SdoProtType)
2669
2670
2671 Exit:
2672     return Ret;
2673
2674 }
2675 #endif
2676 //---------------------------------------------------------------------------
2677 //
2678 // Function:        EplSdoComClientProcessFrame
2679 //
2680 // Description:    function process a received frame
2681 //
2682 //
2683 //
2684 // Parameters:      SdoComCon_p      = connection handle
2685 //                  pAsySdoCom_p     = pointer to frame to process
2686 //
2687 // Returns:         tEplKernel  =  errorcode
2688 //
2689 //
2690 // State:
2691 //
2692 //---------------------------------------------------------------------------
2693 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
2694 static tEplKernel EplSdoComClientProcessFrame(tEplSdoComConHdl   SdoComCon_p,
2695                                               tEplAsySdoCom*     pAsySdoCom_p)
2696 {
2697 tEplKernel          Ret;
2698 BYTE                bBuffer;
2699 unsigned int        uiBuffer;
2700 unsigned int        uiDataSize;
2701 unsigned long       ulBuffer;
2702 tEplSdoComCon*      pSdoComCon;
2703
2704
2705     Ret = kEplSuccessful;
2706
2707     // get pointer to control structure
2708     pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComCon_p];
2709
2710     // check if transaction Id fit
2711     bBuffer = AmiGetByteFromLe(&pAsySdoCom_p->m_le_bTransactionId);
2712     if(pSdoComCon->m_bTransactionId != bBuffer)
2713     {
2714         // incorrect transaction id
2715
2716         // if running transfer
2717         if((pSdoComCon->m_uiTransferredByte != 0)
2718             && (pSdoComCon->m_uiTransSize !=0))
2719         {
2720             pSdoComCon->m_dwLastAbortCode = EPL_SDOAC_GENERAL_ERROR;
2721             // -> send abort
2722             EplSdoComClientSendAbort(pSdoComCon, pSdoComCon->m_dwLastAbortCode);
2723             // call callback of application
2724             Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferTxAborted);
2725         }
2726
2727     }
2728     else
2729     {   // check if correct command
2730         bBuffer = AmiGetByteFromLe(&pAsySdoCom_p->m_le_bCommandId);
2731         if(pSdoComCon->m_SdoServiceType != bBuffer)
2732         {
2733             // incorrect command
2734             // if running transfer
2735             if((pSdoComCon->m_uiTransferredByte != 0)
2736                 && (pSdoComCon->m_uiTransSize !=0))
2737             {
2738                 pSdoComCon->m_dwLastAbortCode = EPL_SDOAC_GENERAL_ERROR;
2739                 // -> send abort
2740                 EplSdoComClientSendAbort(pSdoComCon, pSdoComCon->m_dwLastAbortCode);
2741                 // call callback of application
2742                 Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferTxAborted);
2743             }
2744
2745         }
2746         else
2747         {   // switch on command
2748             switch(pSdoComCon->m_SdoServiceType)
2749             {
2750                 case kEplSdoServiceWriteByIndex:
2751                 {   // check if confirmation from server
2752                     // nothing more to do
2753                     break;
2754                 }
2755
2756                 case kEplSdoServiceReadByIndex:
2757                 {   // check if it is an segmented or an expedited transfer
2758                     bBuffer = AmiGetByteFromLe(&pAsySdoCom_p->m_le_bFlags);
2759                     // mask uninteressting bits
2760                     bBuffer &= 0x30;
2761                     switch(bBuffer)
2762                     {
2763                         // expedited transfer
2764                         case 0x00:
2765                         {
2766                             // check size of buffer
2767                             uiBuffer = AmiGetWordFromLe(&pAsySdoCom_p->m_le_wSegmentSize);
2768                             if(uiBuffer > pSdoComCon->m_uiTransSize)
2769                             {   // buffer provided by the application is to small
2770                                 // copy only a part
2771                                 uiDataSize = pSdoComCon->m_uiTransSize;
2772                             }
2773                             else
2774                             {   // buffer fits
2775                                 uiDataSize = uiBuffer;
2776                             }
2777
2778                             // copy data
2779                             EPL_MEMCPY(pSdoComCon->m_pData, &pAsySdoCom_p->m_le_abCommandData[0], uiDataSize);
2780
2781                             // correct counter
2782                             pSdoComCon->m_uiTransSize = 0;
2783                             pSdoComCon->m_uiTransferredByte = uiDataSize;
2784                             break;
2785                         }
2786
2787                         // start of a segmented transfer
2788                         case 0x10:
2789                         {   // get total size of transfer
2790                             ulBuffer = AmiGetDwordFromLe(&pAsySdoCom_p->m_le_abCommandData[0]);
2791                             if(ulBuffer <= pSdoComCon->m_uiTransSize)
2792                             {   // buffer fit
2793                                 pSdoComCon->m_uiTransSize = (unsigned int)ulBuffer;
2794                             }
2795                             else
2796                             {   // buffer to small
2797                                 // send abort
2798                                 pSdoComCon->m_dwLastAbortCode = EPL_SDOAC_DATA_TYPE_LENGTH_TOO_HIGH;
2799                                 // -> send abort
2800                                 EplSdoComClientSendAbort(pSdoComCon, pSdoComCon->m_dwLastAbortCode);
2801                                 // call callback of application
2802                                 Ret = EplSdoComTransferFinished(SdoComCon_p, pSdoComCon, kEplSdoComTransferRxAborted);
2803                                 goto Exit;
2804                             }
2805
2806                             // get segment size
2807                             // check size of buffer
2808                             uiBuffer = AmiGetWordFromLe(&pAsySdoCom_p->m_le_wSegmentSize);
2809                             // subtract size of vaiable header from datasize
2810                             uiBuffer -= 4;
2811                             // copy data
2812                             EPL_MEMCPY(pSdoComCon->m_pData, &pAsySdoCom_p->m_le_abCommandData[4], uiBuffer);
2813
2814                             // correct counter an pointer
2815                             pSdoComCon->m_pData += uiBuffer;
2816                             pSdoComCon->m_uiTransferredByte += uiBuffer;
2817                             pSdoComCon->m_uiTransSize -= uiBuffer;
2818
2819                             break;
2820                         }
2821
2822                         // segment
2823                         case 0x20:
2824                         {
2825                             // get segment size
2826                             // check size of buffer
2827                             uiBuffer = AmiGetWordFromLe(&pAsySdoCom_p->m_le_wSegmentSize);
2828                             // check if data to copy fit to buffer
2829                             if(uiBuffer >= pSdoComCon->m_uiTransSize)
2830                             {   // to much data
2831                                 uiBuffer =  (pSdoComCon->m_uiTransSize - 1);
2832                             }
2833                             // copy data
2834                             EPL_MEMCPY(pSdoComCon->m_pData, &pAsySdoCom_p->m_le_abCommandData[0], uiBuffer);
2835
2836                             // correct counter an pointer
2837                             pSdoComCon->m_pData += uiBuffer;
2838                             pSdoComCon->m_uiTransferredByte += uiBuffer;
2839                             pSdoComCon->m_uiTransSize -= uiBuffer;
2840                             break;
2841                         }
2842
2843                         // last segment
2844                         case 0x30:
2845                         {
2846                             // get segment size
2847                             // check size of buffer
2848                             uiBuffer = AmiGetWordFromLe(&pAsySdoCom_p->m_le_wSegmentSize);
2849                             // check if data to copy fit to buffer
2850                             if(uiBuffer > pSdoComCon->m_uiTransSize)
2851                             {   // to much data
2852                                 uiBuffer =  (pSdoComCon->m_uiTransSize - 1);
2853                             }
2854                             // copy data
2855                             EPL_MEMCPY(pSdoComCon->m_pData, &pAsySdoCom_p->m_le_abCommandData[0], uiBuffer);
2856
2857                             // correct counter an pointer
2858                             pSdoComCon->m_pData += uiBuffer;
2859                             pSdoComCon->m_uiTransferredByte += uiBuffer;
2860                             pSdoComCon->m_uiTransSize  = 0;
2861
2862                             break;
2863                         }
2864                     }// end of switch(bBuffer & 0x30)
2865
2866                     break;
2867                 }
2868
2869                 case kEplSdoServiceNIL:
2870                 default:
2871                     // invalid service requested
2872                     // $$$ d.k. What should we do?
2873                     break;
2874             }// end of switch(pSdoComCon->m_SdoServiceType)
2875         }
2876     }
2877
2878 Exit:
2879     return Ret;
2880 }
2881 #endif
2882
2883 //---------------------------------------------------------------------------
2884 //
2885 // Function:    EplSdoComClientSendAbort
2886 //
2887 // Description: function send a abort message
2888 //
2889 //
2890 //
2891 // Parameters:  pSdoComCon_p     = pointer to control structure of connection
2892 //              dwAbortCode_p    = Sdo abort code
2893 //
2894 // Returns:     tEplKernel  =  errorcode
2895 //
2896 //
2897 // State:
2898 //
2899 //---------------------------------------------------------------------------
2900 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
2901 static tEplKernel EplSdoComClientSendAbort(tEplSdoComCon* pSdoComCon_p,
2902                                            DWORD          dwAbortCode_p)
2903 {
2904 tEplKernel      Ret;
2905 BYTE            abFrame[EPL_MAX_SDO_FRAME_SIZE];
2906 tEplFrame*      pFrame;
2907 tEplAsySdoCom*  pCommandFrame;
2908 unsigned int    uiSizeOfFrame;
2909
2910     Ret = kEplSuccessful;
2911
2912     pFrame = (tEplFrame*)&abFrame[0];
2913
2914     EPL_MEMSET(&abFrame[0], 0x00, sizeof(abFrame));
2915
2916     // build generic part of frame
2917     // get pointer to command layerpart of frame
2918     pCommandFrame = &pFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame.m_le_abSdoSeqPayload;
2919     AmiSetByteToLe( &pCommandFrame->m_le_bCommandId, pSdoComCon_p->m_SdoServiceType);
2920     AmiSetByteToLe( &pCommandFrame->m_le_bTransactionId, pSdoComCon_p->m_bTransactionId);
2921
2922     uiSizeOfFrame = 8;
2923
2924     // set response and abort flag
2925     pCommandFrame->m_le_bFlags |= 0x40;
2926
2927     // copy abortcode to frame
2928     AmiSetDwordToLe(&pCommandFrame->m_le_abCommandData[0], dwAbortCode_p);
2929
2930     // set size of segment
2931     AmiSetWordToLe(&pCommandFrame->m_le_wSegmentSize, sizeof(DWORD));
2932
2933     // update counter
2934     pSdoComCon_p->m_uiTransferredByte = sizeof(DWORD);
2935     pSdoComCon_p->m_uiTransSize = 0;
2936
2937     // calc framesize
2938     uiSizeOfFrame += sizeof(DWORD);
2939
2940     // save abort code
2941     pSdoComCon_p->m_dwLastAbortCode = dwAbortCode_p;
2942
2943     // call send function of lower layer
2944     switch(pSdoComCon_p->m_SdoProtType)
2945     {
2946         case kEplSdoTypeAsnd:
2947         case kEplSdoTypeUdp:
2948         {
2949             Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl,
2950                                         uiSizeOfFrame,
2951                                         pFrame);
2952             break;
2953         }
2954
2955         default:
2956         {
2957             Ret = kEplSdoComUnsupportedProt;
2958         }
2959     } // end of switch(pSdoComCon_p->m_SdoProtType)
2960
2961
2962     return Ret;
2963 }
2964 #endif
2965
2966 //---------------------------------------------------------------------------
2967 //
2968 // Function:    EplSdoComTransferFinished
2969 //
2970 // Description: calls callback function of application if available
2971 //              and clears entry in control structure
2972 //
2973 // Parameters:  pSdoComCon_p     = pointer to control structure of connection
2974 //              SdoComConState_p = state of SDO transfer
2975 //
2976 // Returns:     tEplKernel  =  errorcode
2977 //
2978 //
2979 // State:
2980 //
2981 //---------------------------------------------------------------------------
2982 static tEplKernel EplSdoComTransferFinished(tEplSdoComConHdl   SdoComCon_p,
2983                                             tEplSdoComCon*     pSdoComCon_p,
2984                                             tEplSdoComConState SdoComConState_p)
2985 {
2986 tEplKernel      Ret;
2987
2988     Ret = kEplSuccessful;
2989
2990     if(pSdoComCon_p->m_pfnTransferFinished != NULL)
2991     {
2992     tEplSdoFinishedCb   pfnTransferFinished;
2993     tEplSdoComFinished  SdoComFinished;
2994
2995         SdoComFinished.m_pUserArg = pSdoComCon_p->m_pUserArg;
2996         SdoComFinished.m_uiNodeId = pSdoComCon_p->m_uiNodeId;
2997         SdoComFinished.m_uiTargetIndex = pSdoComCon_p->m_uiTargetIndex;
2998         SdoComFinished.m_uiTargetSubIndex = pSdoComCon_p->m_uiTargetSubIndex;
2999         SdoComFinished.m_uiTransferredByte = pSdoComCon_p->m_uiTransferredByte;
3000         SdoComFinished.m_dwAbortCode = pSdoComCon_p->m_dwLastAbortCode;
3001         SdoComFinished.m_SdoComConHdl = SdoComCon_p;
3002         SdoComFinished.m_SdoComConState = SdoComConState_p;
3003         if (pSdoComCon_p->m_SdoServiceType == kEplSdoServiceWriteByIndex)
3004         {
3005             SdoComFinished.m_SdoAccessType = kEplSdoAccessTypeWrite;
3006         }
3007         else
3008         {
3009             SdoComFinished.m_SdoAccessType = kEplSdoAccessTypeRead;
3010         }
3011
3012         // reset transfer state so this handle is not busy anymore
3013         pSdoComCon_p->m_uiTransferredByte = 0;
3014         pSdoComCon_p->m_uiTransSize = 0;
3015
3016         pfnTransferFinished = pSdoComCon_p->m_pfnTransferFinished;
3017         // delete function pointer to inform application only once for each transfer
3018         pSdoComCon_p->m_pfnTransferFinished = NULL;
3019
3020         // call application's callback function
3021         pfnTransferFinished(&SdoComFinished);
3022
3023     }
3024
3025     return Ret;
3026 }
3027
3028 // EOF
3029