• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 //---------------------------------------------------------------------------
EplSdoUdpuInit(tEplSequLayerReceiveCb fpReceiveCb_p)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 //---------------------------------------------------------------------------
EplSdoUdpuAddInstance(tEplSequLayerReceiveCb fpReceiveCb_p)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 //---------------------------------------------------------------------------
EplSdoUdpuDelInstance()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 //---------------------------------------------------------------------------
EplSdoUdpuConfig(unsigned long ulIpAddr_p,unsigned int uiPort_p)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 //---------------------------------------------------------------------------
EplSdoUdpuInitCon(tEplSdoConHdl * pSdoConHandle_p,unsigned int uiTargetNodeId_p)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 //---------------------------------------------------------------------------
EplSdoUdpuSendData(tEplSdoConHdl SdoConHandle_p,tEplFrame * pSrcData_p,DWORD dwDataSize_p)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 //---------------------------------------------------------------------------
EplSdoUdpuDelCon(tEplSdoConHdl SdoConHandle_p)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_)
EplSdoUdpThread(LPVOID lpParameter)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
791