Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
[linux-2.6] / drivers / staging / epl / EplSdoUdpu.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/UDP-Protocolabstractionlayer 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: EplSdoUdpu.c,v $
53
54                 $Author: D.Krueger $
55
56                 $Revision: 1.8 $  $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/EplSdoUdpu.h"
72
73 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
74
75 #if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
76 #include "SocketLinuxKernel.h"
77 #include <linux/completion.h>
78 #include <linux/sched.h>
79 #endif
80
81 /***************************************************************************/
82 /*                                                                         */
83 /*                                                                         */
84 /*          G L O B A L   D E F I N I T I O N S                            */
85 /*                                                                         */
86 /*                                                                         */
87 /***************************************************************************/
88
89 //---------------------------------------------------------------------------
90 // const defines
91 //---------------------------------------------------------------------------
92
93 #ifndef EPL_SDO_MAX_CONNECTION_UDP
94 #define EPL_SDO_MAX_CONNECTION_UDP  5
95 #endif
96
97 //---------------------------------------------------------------------------
98 // local types
99 //---------------------------------------------------------------------------
100
101 typedef struct {
102         unsigned long m_ulIpAddr;       // in network byte order
103         unsigned int m_uiPort;  // in network byte order
104
105 } tEplSdoUdpCon;
106
107 // instance table
108 typedef struct {
109         tEplSdoUdpCon m_aSdoAbsUdpConnection[EPL_SDO_MAX_CONNECTION_UDP];
110         tEplSequLayerReceiveCb m_fpSdoAsySeqCb;
111         SOCKET m_UdpSocket;
112
113 #if (TARGET_SYSTEM == _WIN32_)
114         HANDLE m_ThreadHandle;
115         LPCRITICAL_SECTION m_pCriticalSection;
116         CRITICAL_SECTION m_CriticalSection;
117
118 #elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
119         struct completion m_CompletionUdpThread;
120         int m_ThreadHandle;
121         int m_iTerminateThread;
122 #endif
123
124 } tEplSdoUdpInstance;
125
126 //---------------------------------------------------------------------------
127 // modul globale vars
128 //---------------------------------------------------------------------------
129
130 static tEplSdoUdpInstance SdoUdpInstance_g;
131
132 //---------------------------------------------------------------------------
133 // local function prototypes
134 //---------------------------------------------------------------------------
135
136 #if (TARGET_SYSTEM == _WIN32_)
137 static DWORD PUBLIC EplSdoUdpThread(LPVOID lpParameter);
138
139 #elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
140 static int EplSdoUdpThread(void *pArg_p);
141 #endif
142
143 /***************************************************************************/
144 /*                                                                         */
145 /*                                                                         */
146 /*          C L A S S  <EPL-SDO-UDP-Layer>                                 */
147 /*                                                                         */
148 /*                                                                         */
149 /***************************************************************************/
150 //
151 // Description: Protocolabstraction layer for UDP
152 //
153 //
154 /***************************************************************************/
155
156 //=========================================================================//
157 //                                                                         //
158 //          P U B L I C   F U N C T I O N S                                //
159 //                                                                         //
160 //=========================================================================//
161
162 //---------------------------------------------------------------------------
163 //
164 // Function:    EplSdoUdpuInit
165 //
166 // Description: init first instance of the module
167 //
168 //
169 //
170 // Parameters:  pReceiveCb_p    =   functionpointer to Sdo-Sequence layer
171 //                                  callback-function
172 //
173 //
174 // Returns:     tEplKernel  = Errorcode
175 //
176 //
177 // State:
178 //
179 //---------------------------------------------------------------------------
180 tEplKernel PUBLIC EplSdoUdpuInit(tEplSequLayerReceiveCb fpReceiveCb_p)
181 {
182         tEplKernel Ret;
183
184         Ret = EplSdoUdpuAddInstance(fpReceiveCb_p);
185
186         return Ret;
187 }
188
189 //---------------------------------------------------------------------------
190 //
191 // Function:    EplSdoUdpuAddInstance
192 //
193 // Description: init additional instance of the module
194 //              înit socket and start Listen-Thread
195 //
196 //
197 //
198 // Parameters:  pReceiveCb_p    =   functionpointer to Sdo-Sequence layer
199 //                                  callback-function
200 //
201 //
202 // Returns:     tEplKernel  = Errorcode
203 //
204 //
205 // State:
206 //
207 //---------------------------------------------------------------------------
208 tEplKernel PUBLIC EplSdoUdpuAddInstance(tEplSequLayerReceiveCb fpReceiveCb_p)
209 {
210         tEplKernel Ret;
211
212 #if (TARGET_SYSTEM == _WIN32_)
213         int iError;
214         WSADATA Wsa;
215
216 #endif
217
218         // set instance variables to 0
219         EPL_MEMSET(&SdoUdpInstance_g, 0x00, sizeof(SdoUdpInstance_g));
220
221         Ret = kEplSuccessful;
222
223         // save pointer to callback-function
224         if (fpReceiveCb_p != NULL) {
225                 SdoUdpInstance_g.m_fpSdoAsySeqCb = fpReceiveCb_p;
226         } else {
227                 Ret = kEplSdoUdpMissCb;
228                 goto Exit;
229         }
230
231 #if (TARGET_SYSTEM == _WIN32_)
232         // start winsock2 for win32
233         // windows specific start of socket
234         iError = WSAStartup(MAKEWORD(2, 0), &Wsa);
235         if (iError != 0) {
236                 Ret = kEplSdoUdpNoSocket;
237                 goto Exit;
238         }
239         // create critical section for acccess of instnace variables
240         SdoUdpInstance_g.m_pCriticalSection =
241             &SdoUdpInstance_g.m_CriticalSection;
242         InitializeCriticalSection(SdoUdpInstance_g.m_pCriticalSection);
243
244 #elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
245         init_completion(&SdoUdpInstance_g.m_CompletionUdpThread);
246         SdoUdpInstance_g.m_iTerminateThread = 0;
247 #endif
248
249         SdoUdpInstance_g.m_ThreadHandle = 0;
250         SdoUdpInstance_g.m_UdpSocket = INVALID_SOCKET;
251
252         Ret = EplSdoUdpuConfig(INADDR_ANY, 0);
253
254       Exit:
255         return Ret;
256 }
257
258 //---------------------------------------------------------------------------
259 //
260 // Function:    EplSdoUdpuDelInstance
261 //
262 // Description: del instance of the module
263 //              del socket and del Listen-Thread
264 //
265 //
266 //
267 // Parameters:
268 //
269 //
270 // Returns:     tEplKernel  = Errorcode
271 //
272 //
273 // State:
274 //
275 //---------------------------------------------------------------------------
276 tEplKernel PUBLIC EplSdoUdpuDelInstance()
277 {
278         tEplKernel Ret;
279
280 #if (TARGET_SYSTEM == _WIN32_)
281         BOOL fTermError;
282 #endif
283
284         Ret = kEplSuccessful;
285
286         if (SdoUdpInstance_g.m_ThreadHandle != 0) {     // listen thread was started
287                 // close thread
288 #if (TARGET_SYSTEM == _WIN32_)
289                 fTermError =
290                     TerminateThread(SdoUdpInstance_g.m_ThreadHandle, 0);
291                 if (fTermError == FALSE) {
292                         Ret = kEplSdoUdpThreadError;
293                         goto Exit;
294                 }
295 #elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
296                 SdoUdpInstance_g.m_iTerminateThread = 1;
297                 /* kill_proc(SdoUdpInstance_g.m_ThreadHandle, SIGTERM, 1 ); */
298                 send_sig(SIGTERM, SdoUdpInstance_g.m_ThreadHandle, 1);
299                 wait_for_completion(&SdoUdpInstance_g.m_CompletionUdpThread);
300 #endif
301
302                 SdoUdpInstance_g.m_ThreadHandle = 0;
303         }
304
305         if (SdoUdpInstance_g.m_UdpSocket != INVALID_SOCKET) {
306                 // close socket
307                 closesocket(SdoUdpInstance_g.m_UdpSocket);
308                 SdoUdpInstance_g.m_UdpSocket = INVALID_SOCKET;
309         }
310 #if (TARGET_SYSTEM == _WIN32_)
311         // delete critical section
312         DeleteCriticalSection(SdoUdpInstance_g.m_pCriticalSection);
313 #endif
314
315 #if (TARGET_SYSTEM == _WIN32_)
316         // for win 32
317         WSACleanup();
318 #endif
319
320 #if (TARGET_SYSTEM == _WIN32_)
321       Exit:
322 #endif
323         return Ret;
324 }
325
326 //---------------------------------------------------------------------------
327 //
328 // Function:    EplSdoUdpuConfig
329 //
330 // Description: reconfigurate socket with new IP-Address
331 //              -> needed for NMT ResetConfiguration
332 //
333 // Parameters:  ulIpAddr_p      = IpAddress in platform byte order
334 //              uiPort_p        = port number in platform byte order
335 //
336 //
337 // Returns:     tEplKernel  = Errorcode
338 //
339 //
340 // State:
341 //
342 //---------------------------------------------------------------------------
343 tEplKernel PUBLIC EplSdoUdpuConfig(unsigned long ulIpAddr_p,
344                                    unsigned int uiPort_p)
345 {
346         tEplKernel Ret;
347         struct sockaddr_in Addr;
348         int iError;
349
350 #if (TARGET_SYSTEM == _WIN32_)
351         BOOL fTermError;
352         unsigned long ulThreadId;
353 #endif
354
355         Ret = kEplSuccessful;
356
357         if (uiPort_p == 0) {    // set UDP port to default port number
358                 uiPort_p = EPL_C_SDO_EPL_PORT;
359         } else if (uiPort_p > 65535) {
360                 Ret = kEplSdoUdpSocketError;
361                 goto Exit;
362         }
363
364         if (SdoUdpInstance_g.m_ThreadHandle != 0) {     // listen thread was started
365
366                 // close old thread
367 #if (TARGET_SYSTEM == _WIN32_)
368                 fTermError =
369                     TerminateThread(SdoUdpInstance_g.m_ThreadHandle, 0);
370                 if (fTermError == FALSE) {
371                         Ret = kEplSdoUdpThreadError;
372                         goto Exit;
373                 }
374 #elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
375                 SdoUdpInstance_g.m_iTerminateThread = 1;
376                 /* kill_proc(SdoUdpInstance_g.m_ThreadHandle, SIGTERM, 1 ); */
377                 send_sig(SIGTERM, SdoUdpInstance_g.m_ThreadHandle, 1);
378                 wait_for_completion(&SdoUdpInstance_g.m_CompletionUdpThread);
379                 SdoUdpInstance_g.m_iTerminateThread = 0;
380 #endif
381
382                 SdoUdpInstance_g.m_ThreadHandle = 0;
383         }
384
385         if (SdoUdpInstance_g.m_UdpSocket != INVALID_SOCKET) {
386                 // close socket
387                 iError = closesocket(SdoUdpInstance_g.m_UdpSocket);
388                 SdoUdpInstance_g.m_UdpSocket = INVALID_SOCKET;
389                 if (iError != 0) {
390                         Ret = kEplSdoUdpSocketError;
391                         goto Exit;
392                 }
393         }
394         // create Socket
395         SdoUdpInstance_g.m_UdpSocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
396         if (SdoUdpInstance_g.m_UdpSocket == INVALID_SOCKET) {
397                 Ret = kEplSdoUdpNoSocket;
398                 EPL_DBGLVL_SDO_TRACE0("EplSdoUdpuConfig: socket() failed\n");
399                 goto Exit;
400         }
401         // bind socket
402         Addr.sin_family = AF_INET;
403         Addr.sin_port = htons((unsigned short)uiPort_p);
404         Addr.sin_addr.s_addr = htonl(ulIpAddr_p);
405         iError =
406             bind(SdoUdpInstance_g.m_UdpSocket, (struct sockaddr *)&Addr,
407                  sizeof(Addr));
408         if (iError < 0) {
409                 //iError = WSAGetLastError();
410                 EPL_DBGLVL_SDO_TRACE1
411                     ("EplSdoUdpuConfig: bind() finished with %i\n", iError);
412                 Ret = kEplSdoUdpNoSocket;
413                 goto Exit;
414         }
415         // create Listen-Thread
416 #if (TARGET_SYSTEM == _WIN32_)
417         // for win32
418
419         // create thread
420         SdoUdpInstance_g.m_ThreadHandle = CreateThread(NULL,
421                                                        0,
422                                                        EplSdoUdpThread,
423                                                        &SdoUdpInstance_g,
424                                                        0, &ulThreadId);
425         if (SdoUdpInstance_g.m_ThreadHandle == NULL) {
426                 Ret = kEplSdoUdpThreadError;
427                 goto Exit;
428         }
429 #elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
430
431         SdoUdpInstance_g.m_ThreadHandle =
432             kernel_thread(EplSdoUdpThread, &SdoUdpInstance_g, CLONE_KERNEL);
433         if (SdoUdpInstance_g.m_ThreadHandle == 0) {
434                 Ret = kEplSdoUdpThreadError;
435                 goto Exit;
436         }
437 #endif
438
439       Exit:
440         return Ret;
441
442 }
443
444 //---------------------------------------------------------------------------
445 //
446 // Function:    EplSdoUdpuInitCon
447 //
448 // Description: init a new connect
449 //
450 //
451 //
452 // Parameters:  pSdoConHandle_p = pointer for the new connection handle
453 //              uiTargetNodeId_p = NodeId of the target node
454 //
455 //
456 // Returns:     tEplKernel  = Errorcode
457 //
458 //
459 // State:
460 //
461 //---------------------------------------------------------------------------
462 tEplKernel PUBLIC EplSdoUdpuInitCon(tEplSdoConHdl * pSdoConHandle_p,
463                                     unsigned int uiTargetNodeId_p)
464 {
465         tEplKernel Ret;
466         unsigned int uiCount;
467         unsigned int uiFreeCon;
468         tEplSdoUdpCon *pSdoUdpCon;
469
470         Ret = kEplSuccessful;
471
472         // get free entry in control structure
473         uiCount = 0;
474         uiFreeCon = EPL_SDO_MAX_CONNECTION_UDP;
475         pSdoUdpCon = &SdoUdpInstance_g.m_aSdoAbsUdpConnection[0];
476         while (uiCount < EPL_SDO_MAX_CONNECTION_UDP) {
477                 if ((pSdoUdpCon->m_ulIpAddr & htonl(0xFF)) == htonl(uiTargetNodeId_p)) {        // existing connection to target node found
478                         // set handle
479                         *pSdoConHandle_p = (uiCount | EPL_SDO_UDP_HANDLE);
480
481                         goto Exit;
482                 } else if ((pSdoUdpCon->m_ulIpAddr == 0)
483                            && (pSdoUdpCon->m_uiPort == 0)) {
484                         uiFreeCon = uiCount;
485                 }
486                 uiCount++;
487                 pSdoUdpCon++;
488         }
489
490         if (uiFreeCon == EPL_SDO_MAX_CONNECTION_UDP) {
491                 // error no free handle
492                 Ret = kEplSdoUdpNoFreeHandle;
493         } else {
494                 pSdoUdpCon =
495                     &SdoUdpInstance_g.m_aSdoAbsUdpConnection[uiFreeCon];
496                 // save infos for connection
497                 pSdoUdpCon->m_uiPort = htons(EPL_C_SDO_EPL_PORT);
498                 pSdoUdpCon->m_ulIpAddr = htonl(0xC0A86400 | uiTargetNodeId_p);  // 192.168.100.uiTargetNodeId_p
499
500                 // set handle
501                 *pSdoConHandle_p = (uiFreeCon | EPL_SDO_UDP_HANDLE);
502
503         }
504
505       Exit:
506         return Ret;
507
508 }
509
510 //---------------------------------------------------------------------------
511 //
512 // Function:    EplSdoUdpuSendData
513 //
514 // Description: send data using exisiting connection
515 //
516 //
517 //
518 // Parameters:  SdoConHandle_p  = connection handle
519 //              pSrcData_p      = pointer to data
520 //              dwDataSize_p    = number of databyte
521 //                                  -> without asend-header!!!
522 //
523 // Returns:     tEplKernel  = Errorcode
524 //
525 //
526 // State:
527 //
528 //---------------------------------------------------------------------------
529 tEplKernel PUBLIC EplSdoUdpuSendData(tEplSdoConHdl SdoConHandle_p,
530                                      tEplFrame * pSrcData_p, DWORD dwDataSize_p)
531 {
532         tEplKernel Ret;
533         int iError;
534         unsigned int uiArray;
535         struct sockaddr_in Addr;
536
537         Ret = kEplSuccessful;
538
539         uiArray = (SdoConHandle_p & ~EPL_SDO_ASY_HANDLE_MASK);
540         if (uiArray >= EPL_SDO_MAX_CONNECTION_UDP) {
541                 Ret = kEplSdoUdpInvalidHdl;
542                 goto Exit;
543         }
544         //set message type
545         AmiSetByteToLe(&pSrcData_p->m_le_bMessageType, 0x06);   // SDO
546         // target node id (for Udp = 0)
547         AmiSetByteToLe(&pSrcData_p->m_le_bDstNodeId, 0x00);
548         // set source-nodeid (for Udp = 0)
549         AmiSetByteToLe(&pSrcData_p->m_le_bSrcNodeId, 0x00);
550
551         // calc size
552         dwDataSize_p += EPL_ASND_HEADER_SIZE;
553
554         // call sendto
555         Addr.sin_family = AF_INET;
556 #if (TARGET_SYSTEM == _WIN32_)
557         // enter  critical section for process function
558         EnterCriticalSection(SdoUdpInstance_g.m_pCriticalSection);
559 #endif
560
561         Addr.sin_port =
562             (unsigned short)SdoUdpInstance_g.m_aSdoAbsUdpConnection[uiArray].
563             m_uiPort;
564         Addr.sin_addr.s_addr =
565             SdoUdpInstance_g.m_aSdoAbsUdpConnection[uiArray].m_ulIpAddr;
566
567 #if (TARGET_SYSTEM == _WIN32_)
568         // leave critical section for process function
569         LeaveCriticalSection(SdoUdpInstance_g.m_pCriticalSection);
570 #endif
571
572         iError = sendto(SdoUdpInstance_g.m_UdpSocket,   // sockethandle
573                         (const char *)&pSrcData_p->m_le_bMessageType,   // data to send
574                         dwDataSize_p,   // number of bytes to send
575                         0,      // flags
576                         (struct sockaddr *)&Addr,       // target
577                         sizeof(struct sockaddr_in));    // sizeof targetadress
578         if (iError < 0) {
579                 EPL_DBGLVL_SDO_TRACE1
580                     ("EplSdoUdpuSendData: sendto() finished with %i\n", iError);
581                 Ret = kEplSdoUdpSendError;
582                 goto Exit;
583         }
584
585       Exit:
586         return Ret;
587
588 }
589
590 //---------------------------------------------------------------------------
591 //
592 // Function:    EplSdoUdpuDelCon
593 //
594 // Description: delete connection from intern structure
595 //
596 //
597 //
598 // Parameters:  SdoConHandle_p  = connection handle
599 //
600 // Returns:     tEplKernel  = Errorcode
601 //
602 //
603 // State:
604 //
605 //---------------------------------------------------------------------------
606 tEplKernel PUBLIC EplSdoUdpuDelCon(tEplSdoConHdl SdoConHandle_p)
607 {
608         tEplKernel Ret;
609         unsigned int uiArray;
610
611         uiArray = (SdoConHandle_p & ~EPL_SDO_ASY_HANDLE_MASK);
612
613         if (uiArray >= EPL_SDO_MAX_CONNECTION_UDP) {
614                 Ret = kEplSdoUdpInvalidHdl;
615                 goto Exit;
616         } else {
617                 Ret = kEplSuccessful;
618         }
619
620         // delete connection
621         SdoUdpInstance_g.m_aSdoAbsUdpConnection[uiArray].m_ulIpAddr = 0;
622         SdoUdpInstance_g.m_aSdoAbsUdpConnection[uiArray].m_uiPort = 0;
623
624       Exit:
625         return Ret;
626 }
627
628 //=========================================================================//
629 //                                                                         //
630 //          P R I V A T E   F U N C T I O N S                              //
631 //                                                                         //
632 //=========================================================================//
633
634 //---------------------------------------------------------------------------
635 //
636 // Function:        EplSdoUdpThread
637 //
638 // Description:     thread check socket for new data
639 //
640 //
641 //
642 // Parameters:      lpParameter = pointer to parameter type tEplSdoUdpThreadPara
643 //
644 //
645 // Returns:         DWORD   =   errorcode
646 //
647 //
648 // State:
649 //
650 //---------------------------------------------------------------------------
651 #if (TARGET_SYSTEM == _WIN32_)
652 static DWORD PUBLIC EplSdoUdpThread(LPVOID lpParameter)
653 #elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
654 static int EplSdoUdpThread(void *pArg_p)
655 #endif
656 {
657
658         tEplSdoUdpInstance *pInstance;
659         struct sockaddr_in RemoteAddr;
660         int iError;
661         int iCount;
662         int iFreeEntry;
663         BYTE abBuffer[EPL_MAX_SDO_REC_FRAME_SIZE];
664         unsigned int uiSize;
665         tEplSdoConHdl SdoConHdl;
666
667 #if (TARGET_SYSTEM == _WIN32_)
668         pInstance = (tEplSdoUdpInstance *) lpParameter;
669
670         for (;;)
671 #elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
672         pInstance = (tEplSdoUdpInstance *) pArg_p;
673         daemonize("EplSdoUdpThread");
674         allow_signal(SIGTERM);
675
676         for (; pInstance->m_iTerminateThread == 0;)
677 #endif
678
679         {
680                 // wait for data
681                 uiSize = sizeof(struct sockaddr);
682                 iError = recvfrom(pInstance->m_UdpSocket,       // Socket
683                                   (char *)&abBuffer[0], // buffer for data
684                                   sizeof(abBuffer),     // size of the buffer
685                                   0,    // flags
686                                   (struct sockaddr *)&RemoteAddr,
687                                   (int *)&uiSize);
688 #if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
689                 if (iError == -ERESTARTSYS) {
690                         break;
691                 }
692 #endif
693                 if (iError > 0) {
694                         // get handle for higher layer
695                         iCount = 0;
696                         iFreeEntry = 0xFFFF;
697 #if (TARGET_SYSTEM == _WIN32_)
698                         // enter  critical section for process function
699                         EnterCriticalSection(SdoUdpInstance_g.
700                                              m_pCriticalSection);
701 #endif
702                         while (iCount < EPL_SDO_MAX_CONNECTION_UDP) {
703                                 // check if this connection is already known
704                                 if ((pInstance->m_aSdoAbsUdpConnection[iCount].
705                                      m_ulIpAddr == RemoteAddr.sin_addr.s_addr)
706                                     && (pInstance->
707                                         m_aSdoAbsUdpConnection[iCount].
708                                         m_uiPort == RemoteAddr.sin_port)) {
709                                         break;
710                                 }
711
712                                 if ((pInstance->m_aSdoAbsUdpConnection[iCount].
713                                      m_ulIpAddr == 0)
714                                     && (pInstance->
715                                         m_aSdoAbsUdpConnection[iCount].
716                                         m_uiPort == 0)
717                                     && (iFreeEntry == 0xFFFF))
718                                 {
719                                         iFreeEntry = iCount;
720                                 }
721
722                                 iCount++;
723                         }
724
725                         if (iCount == EPL_SDO_MAX_CONNECTION_UDP) {
726                                 // connection unknown
727                                 // see if there is a free handle
728                                 if (iFreeEntry != 0xFFFF) {
729                                         // save adress infos
730                                         pInstance->
731                                             m_aSdoAbsUdpConnection[iFreeEntry].
732                                             m_ulIpAddr =
733                                             RemoteAddr.sin_addr.s_addr;
734                                         pInstance->
735                                             m_aSdoAbsUdpConnection[iFreeEntry].
736                                             m_uiPort = RemoteAddr.sin_port;
737 #if (TARGET_SYSTEM == _WIN32_)
738                                         // leave critical section for process function
739                                         LeaveCriticalSection(SdoUdpInstance_g.
740                                                              m_pCriticalSection);
741 #endif
742                                         // call callback
743                                         SdoConHdl = iFreeEntry;
744                                         SdoConHdl |= EPL_SDO_UDP_HANDLE;
745                                         // offset 4 -> start of SDO Sequence header
746                                         pInstance->m_fpSdoAsySeqCb(SdoConHdl,
747                                                                    (tEplAsySdoSeq
748                                                                     *) &
749                                                                    abBuffer[4],
750                                                                    (iError -
751                                                                     4));
752                                 } else {
753                                         EPL_DBGLVL_SDO_TRACE0
754                                             ("Error in EplSdoUdpThread() no free handle\n");
755 #if (TARGET_SYSTEM == _WIN32_)
756                                         // leave critical section for process function
757                                         LeaveCriticalSection(SdoUdpInstance_g.
758                                                              m_pCriticalSection);
759 #endif
760                                 }
761
762                         } else {
763                                 // known connection
764                                 // call callback with correct handle
765                                 SdoConHdl = iCount;
766                                 SdoConHdl |= EPL_SDO_UDP_HANDLE;
767 #if (TARGET_SYSTEM == _WIN32_)
768                                 // leave critical section for process function
769                                 LeaveCriticalSection(SdoUdpInstance_g.
770                                                      m_pCriticalSection);
771 #endif
772                                 // offset 4 -> start of SDO Sequence header
773                                 pInstance->m_fpSdoAsySeqCb(SdoConHdl,
774                                                            (tEplAsySdoSeq *) &
775                                                            abBuffer[4],
776                                                            (iError - 4));
777                         }
778                 }               // end of  if(iError!=SOCKET_ERROR)
779         }                       // end of for(;;)
780
781 #if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
782         complete_and_exit(&SdoUdpInstance_g.m_CompletionUdpThread, 0);
783 #endif
784
785         return 0;
786 }
787
788 #endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
789
790 // EOF