perf record: Add missing -C option support for specifying profile cpu
[linux-2.6/mini2440.git] / drivers / staging / epl / EplSdoUdpu.c
blobc8e950fa83538ae98b2b626b892d84d4131cee6a
1 /****************************************************************************
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
6 Project: openPOWERLINK
8 Description: source file for SDO/UDP-Protocolabstractionlayer module
10 License:
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions
14 are met:
16 1. Redistributions of source code must retain the above copyright
17 notice, this list of conditions and the following disclaimer.
19 2. Redistributions in binary form must reproduce the above copyright
20 notice, this list of conditions and the following disclaimer in the
21 documentation and/or other materials provided with the distribution.
23 3. Neither the name of SYSTEC electronic GmbH nor the names of its
24 contributors may be used to endorse or promote products derived
25 from this software without prior written permission. For written
26 permission, please contact info@systec-electronic.com.
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32 COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
36 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
38 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 POSSIBILITY OF SUCH DAMAGE.
41 Severability Clause:
43 If a provision of this License is or becomes illegal, invalid or
44 unenforceable in any jurisdiction, that shall not affect:
45 1. the validity or enforceability in that jurisdiction of any other
46 provision of this License; or
47 2. the validity or enforceability in other jurisdictions of that or
48 any other provision of this License.
50 -------------------------------------------------------------------------
52 $RCSfile: EplSdoUdpu.c,v $
54 $Author: D.Krueger $
56 $Revision: 1.8 $ $Date: 2008/10/17 15:32:32 $
58 $State: Exp $
60 Build Environment:
61 GCC V3.4
63 -------------------------------------------------------------------------
65 Revision History:
67 2006/06/26 k.t.: start of the implementation
69 ****************************************************************************/
71 #include "user/EplSdoUdpu.h"
73 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
75 #include "SocketLinuxKernel.h"
76 #include <linux/completion.h>
77 #include <linux/sched.h>
79 /***************************************************************************/
80 /* */
81 /* */
82 /* G L O B A L D E F I N I T I O N S */
83 /* */
84 /* */
85 /***************************************************************************/
87 //---------------------------------------------------------------------------
88 // const defines
89 //---------------------------------------------------------------------------
91 #ifndef EPL_SDO_MAX_CONNECTION_UDP
92 #define EPL_SDO_MAX_CONNECTION_UDP 5
93 #endif
95 //---------------------------------------------------------------------------
96 // local types
97 //---------------------------------------------------------------------------
99 typedef struct {
100 unsigned long m_ulIpAddr; // in network byte order
101 unsigned int m_uiPort; // in network byte order
103 } tEplSdoUdpCon;
105 // instance table
106 typedef struct {
107 tEplSdoUdpCon m_aSdoAbsUdpConnection[EPL_SDO_MAX_CONNECTION_UDP];
108 tEplSequLayerReceiveCb m_fpSdoAsySeqCb;
109 SOCKET m_UdpSocket;
111 struct completion m_CompletionUdpThread;
112 int m_ThreadHandle;
113 int m_iTerminateThread;
114 } tEplSdoUdpInstance;
116 //---------------------------------------------------------------------------
117 // modul globale vars
118 //---------------------------------------------------------------------------
120 static tEplSdoUdpInstance SdoUdpInstance_g;
122 //---------------------------------------------------------------------------
123 // local function prototypes
124 //---------------------------------------------------------------------------
126 static int EplSdoUdpThread(void *pArg_p);
128 /***************************************************************************/
129 /* */
130 /* */
131 /* C L A S S <EPL-SDO-UDP-Layer> */
132 /* */
133 /* */
134 /***************************************************************************/
136 // Description: Protocolabstraction layer for UDP
139 /***************************************************************************/
141 //=========================================================================//
142 // //
143 // P U B L I C F U N C T I O N S //
144 // //
145 //=========================================================================//
147 //---------------------------------------------------------------------------
149 // Function: EplSdoUdpuInit
151 // Description: init first instance of the module
155 // Parameters: pReceiveCb_p = functionpointer to Sdo-Sequence layer
156 // callback-function
159 // Returns: tEplKernel = Errorcode
162 // State:
164 //---------------------------------------------------------------------------
165 tEplKernel EplSdoUdpuInit(tEplSequLayerReceiveCb fpReceiveCb_p)
167 tEplKernel Ret;
169 Ret = EplSdoUdpuAddInstance(fpReceiveCb_p);
171 return Ret;
174 //---------------------------------------------------------------------------
176 // Function: EplSdoUdpuAddInstance
178 // Description: init additional instance of the module
179 // înit socket and start Listen-Thread
183 // Parameters: pReceiveCb_p = functionpointer to Sdo-Sequence layer
184 // callback-function
187 // Returns: tEplKernel = Errorcode
190 // State:
192 //---------------------------------------------------------------------------
193 tEplKernel EplSdoUdpuAddInstance(tEplSequLayerReceiveCb fpReceiveCb_p)
195 tEplKernel Ret;
197 // set instance variables to 0
198 EPL_MEMSET(&SdoUdpInstance_g, 0x00, sizeof(SdoUdpInstance_g));
200 Ret = kEplSuccessful;
202 // save pointer to callback-function
203 if (fpReceiveCb_p != NULL) {
204 SdoUdpInstance_g.m_fpSdoAsySeqCb = fpReceiveCb_p;
205 } else {
206 Ret = kEplSdoUdpMissCb;
207 goto Exit;
210 init_completion(&SdoUdpInstance_g.m_CompletionUdpThread);
211 SdoUdpInstance_g.m_iTerminateThread = 0;
212 SdoUdpInstance_g.m_ThreadHandle = 0;
213 SdoUdpInstance_g.m_UdpSocket = INVALID_SOCKET;
215 Ret = EplSdoUdpuConfig(INADDR_ANY, 0);
217 Exit:
218 return Ret;
221 //---------------------------------------------------------------------------
223 // Function: EplSdoUdpuDelInstance
225 // Description: del instance of the module
226 // del socket and del Listen-Thread
230 // Parameters:
233 // Returns: tEplKernel = Errorcode
236 // State:
238 //---------------------------------------------------------------------------
239 tEplKernel EplSdoUdpuDelInstance(void)
241 tEplKernel Ret;
243 Ret = kEplSuccessful;
245 if (SdoUdpInstance_g.m_ThreadHandle != 0) { // listen thread was started
246 // close thread
247 SdoUdpInstance_g.m_iTerminateThread = 1;
248 /* kill_proc(SdoUdpInstance_g.m_ThreadHandle, SIGTERM, 1 ); */
249 send_sig(SIGTERM, SdoUdpInstance_g.m_ThreadHandle, 1);
250 wait_for_completion(&SdoUdpInstance_g.m_CompletionUdpThread);
251 SdoUdpInstance_g.m_ThreadHandle = 0;
254 if (SdoUdpInstance_g.m_UdpSocket != INVALID_SOCKET) {
255 // close socket
256 closesocket(SdoUdpInstance_g.m_UdpSocket);
257 SdoUdpInstance_g.m_UdpSocket = INVALID_SOCKET;
259 return Ret;
262 //---------------------------------------------------------------------------
264 // Function: EplSdoUdpuConfig
266 // Description: reconfigurate socket with new IP-Address
267 // -> needed for NMT ResetConfiguration
269 // Parameters: ulIpAddr_p = IpAddress in platform byte order
270 // uiPort_p = port number in platform byte order
273 // Returns: tEplKernel = Errorcode
276 // State:
278 //---------------------------------------------------------------------------
279 tEplKernel EplSdoUdpuConfig(unsigned long ulIpAddr_p, unsigned int uiPort_p)
281 tEplKernel Ret;
282 struct sockaddr_in Addr;
283 int iError;
285 Ret = kEplSuccessful;
287 if (uiPort_p == 0) { // set UDP port to default port number
288 uiPort_p = EPL_C_SDO_EPL_PORT;
289 } else if (uiPort_p > 65535) {
290 Ret = kEplSdoUdpSocketError;
291 goto Exit;
294 if (SdoUdpInstance_g.m_ThreadHandle != 0) { // listen thread was started
296 // close old thread
297 SdoUdpInstance_g.m_iTerminateThread = 1;
298 /* kill_proc(SdoUdpInstance_g.m_ThreadHandle, SIGTERM, 1 ); */
299 send_sig(SIGTERM, SdoUdpInstance_g.m_ThreadHandle, 1);
300 wait_for_completion(&SdoUdpInstance_g.m_CompletionUdpThread);
301 SdoUdpInstance_g.m_iTerminateThread = 0;
302 SdoUdpInstance_g.m_ThreadHandle = 0;
305 if (SdoUdpInstance_g.m_UdpSocket != INVALID_SOCKET) {
306 // close socket
307 iError = closesocket(SdoUdpInstance_g.m_UdpSocket);
308 SdoUdpInstance_g.m_UdpSocket = INVALID_SOCKET;
309 if (iError != 0) {
310 Ret = kEplSdoUdpSocketError;
311 goto Exit;
314 // create Socket
315 SdoUdpInstance_g.m_UdpSocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
316 if (SdoUdpInstance_g.m_UdpSocket == INVALID_SOCKET) {
317 Ret = kEplSdoUdpNoSocket;
318 EPL_DBGLVL_SDO_TRACE0("EplSdoUdpuConfig: socket() failed\n");
319 goto Exit;
321 // bind socket
322 Addr.sin_family = AF_INET;
323 Addr.sin_port = htons((unsigned short)uiPort_p);
324 Addr.sin_addr.s_addr = htonl(ulIpAddr_p);
325 iError =
326 bind(SdoUdpInstance_g.m_UdpSocket, (struct sockaddr *)&Addr,
327 sizeof(Addr));
328 if (iError < 0) {
329 //iError = WSAGetLastError();
330 EPL_DBGLVL_SDO_TRACE1
331 ("EplSdoUdpuConfig: bind() finished with %i\n", iError);
332 Ret = kEplSdoUdpNoSocket;
333 goto Exit;
335 // create Listen-Thread
336 SdoUdpInstance_g.m_ThreadHandle =
337 kernel_thread(EplSdoUdpThread, &SdoUdpInstance_g,
338 CLONE_FS | CLONE_FILES);
339 if (SdoUdpInstance_g.m_ThreadHandle == 0) {
340 Ret = kEplSdoUdpThreadError;
341 goto Exit;
344 Exit:
345 return Ret;
349 //---------------------------------------------------------------------------
351 // Function: EplSdoUdpuInitCon
353 // Description: init a new connect
357 // Parameters: pSdoConHandle_p = pointer for the new connection handle
358 // uiTargetNodeId_p = NodeId of the target node
361 // Returns: tEplKernel = Errorcode
364 // State:
366 //---------------------------------------------------------------------------
367 tEplKernel EplSdoUdpuInitCon(tEplSdoConHdl *pSdoConHandle_p,
368 unsigned int uiTargetNodeId_p)
370 tEplKernel Ret;
371 unsigned int uiCount;
372 unsigned int uiFreeCon;
373 tEplSdoUdpCon *pSdoUdpCon;
375 Ret = kEplSuccessful;
377 // get free entry in control structure
378 uiCount = 0;
379 uiFreeCon = EPL_SDO_MAX_CONNECTION_UDP;
380 pSdoUdpCon = &SdoUdpInstance_g.m_aSdoAbsUdpConnection[0];
381 while (uiCount < EPL_SDO_MAX_CONNECTION_UDP) {
382 if ((pSdoUdpCon->m_ulIpAddr & htonl(0xFF)) == htonl(uiTargetNodeId_p)) { // existing connection to target node found
383 // set handle
384 *pSdoConHandle_p = (uiCount | EPL_SDO_UDP_HANDLE);
386 goto Exit;
387 } else if ((pSdoUdpCon->m_ulIpAddr == 0)
388 && (pSdoUdpCon->m_uiPort == 0)) {
389 uiFreeCon = uiCount;
391 uiCount++;
392 pSdoUdpCon++;
395 if (uiFreeCon == EPL_SDO_MAX_CONNECTION_UDP) {
396 // error no free handle
397 Ret = kEplSdoUdpNoFreeHandle;
398 } else {
399 pSdoUdpCon =
400 &SdoUdpInstance_g.m_aSdoAbsUdpConnection[uiFreeCon];
401 // save infos for connection
402 pSdoUdpCon->m_uiPort = htons(EPL_C_SDO_EPL_PORT);
403 pSdoUdpCon->m_ulIpAddr = htonl(0xC0A86400 | uiTargetNodeId_p); // 192.168.100.uiTargetNodeId_p
405 // set handle
406 *pSdoConHandle_p = (uiFreeCon | EPL_SDO_UDP_HANDLE);
410 Exit:
411 return Ret;
415 //---------------------------------------------------------------------------
417 // Function: EplSdoUdpuSendData
419 // Description: send data using exisiting connection
423 // Parameters: SdoConHandle_p = connection handle
424 // pSrcData_p = pointer to data
425 // dwDataSize_p = number of databyte
426 // -> without asend-header!!!
428 // Returns: tEplKernel = Errorcode
431 // State:
433 //---------------------------------------------------------------------------
434 tEplKernel EplSdoUdpuSendData(tEplSdoConHdl SdoConHandle_p,
435 tEplFrame *pSrcData_p, u32 dwDataSize_p)
437 tEplKernel Ret;
438 int iError;
439 unsigned int uiArray;
440 struct sockaddr_in Addr;
442 Ret = kEplSuccessful;
444 uiArray = (SdoConHandle_p & ~EPL_SDO_ASY_HANDLE_MASK);
445 if (uiArray >= EPL_SDO_MAX_CONNECTION_UDP) {
446 Ret = kEplSdoUdpInvalidHdl;
447 goto Exit;
449 //set message type
450 AmiSetByteToLe(&pSrcData_p->m_le_bMessageType, 0x06); // SDO
451 // target node id (for Udp = 0)
452 AmiSetByteToLe(&pSrcData_p->m_le_bDstNodeId, 0x00);
453 // set source-nodeid (for Udp = 0)
454 AmiSetByteToLe(&pSrcData_p->m_le_bSrcNodeId, 0x00);
456 // calc size
457 dwDataSize_p += EPL_ASND_HEADER_SIZE;
459 // call sendto
460 Addr.sin_family = AF_INET;
461 Addr.sin_port =
462 (unsigned short)SdoUdpInstance_g.m_aSdoAbsUdpConnection[uiArray].
463 m_uiPort;
464 Addr.sin_addr.s_addr =
465 SdoUdpInstance_g.m_aSdoAbsUdpConnection[uiArray].m_ulIpAddr;
467 iError = sendto(SdoUdpInstance_g.m_UdpSocket, // sockethandle
468 (const char *)&pSrcData_p->m_le_bMessageType, // data to send
469 dwDataSize_p, // number of bytes to send
470 0, // flags
471 (struct sockaddr *)&Addr, // target
472 sizeof(struct sockaddr_in)); // sizeof targetadress
473 if (iError < 0) {
474 EPL_DBGLVL_SDO_TRACE1
475 ("EplSdoUdpuSendData: sendto() finished with %i\n", iError);
476 Ret = kEplSdoUdpSendError;
477 goto Exit;
480 Exit:
481 return Ret;
485 //---------------------------------------------------------------------------
487 // Function: EplSdoUdpuDelCon
489 // Description: delete connection from intern structure
493 // Parameters: SdoConHandle_p = connection handle
495 // Returns: tEplKernel = Errorcode
498 // State:
500 //---------------------------------------------------------------------------
501 tEplKernel EplSdoUdpuDelCon(tEplSdoConHdl SdoConHandle_p)
503 tEplKernel Ret;
504 unsigned int uiArray;
506 uiArray = (SdoConHandle_p & ~EPL_SDO_ASY_HANDLE_MASK);
508 if (uiArray >= EPL_SDO_MAX_CONNECTION_UDP) {
509 Ret = kEplSdoUdpInvalidHdl;
510 goto Exit;
511 } else {
512 Ret = kEplSuccessful;
515 // delete connection
516 SdoUdpInstance_g.m_aSdoAbsUdpConnection[uiArray].m_ulIpAddr = 0;
517 SdoUdpInstance_g.m_aSdoAbsUdpConnection[uiArray].m_uiPort = 0;
519 Exit:
520 return Ret;
523 //=========================================================================//
524 // //
525 // P R I V A T E F U N C T I O N S //
526 // //
527 //=========================================================================//
529 //---------------------------------------------------------------------------
531 // Function: EplSdoUdpThread
533 // Description: thread check socket for new data
537 // Parameters: lpParameter = pointer to parameter type tEplSdoUdpThreadPara
540 // Returns: u32 = errorcode
543 // State:
545 //---------------------------------------------------------------------------
546 static int EplSdoUdpThread(void *pArg_p)
549 tEplSdoUdpInstance *pInstance;
550 struct sockaddr_in RemoteAddr;
551 int iError;
552 int iCount;
553 int iFreeEntry;
554 u8 abBuffer[EPL_MAX_SDO_REC_FRAME_SIZE];
555 unsigned int uiSize;
556 tEplSdoConHdl SdoConHdl;
558 pInstance = (tEplSdoUdpInstance *) pArg_p;
559 daemonize("EplSdoUdpThread");
560 allow_signal(SIGTERM);
562 for (; pInstance->m_iTerminateThread == 0;)
565 // wait for data
566 uiSize = sizeof(struct sockaddr);
567 iError = recvfrom(pInstance->m_UdpSocket, // Socket
568 (char *)&abBuffer[0], // buffer for data
569 sizeof(abBuffer), // size of the buffer
570 0, // flags
571 (struct sockaddr *)&RemoteAddr,
572 (int *)&uiSize);
573 if (iError == -ERESTARTSYS) {
574 break;
576 if (iError > 0) {
577 // get handle for higher layer
578 iCount = 0;
579 iFreeEntry = 0xFFFF;
580 while (iCount < EPL_SDO_MAX_CONNECTION_UDP) {
581 // check if this connection is already known
582 if ((pInstance->m_aSdoAbsUdpConnection[iCount].
583 m_ulIpAddr == RemoteAddr.sin_addr.s_addr)
584 && (pInstance->
585 m_aSdoAbsUdpConnection[iCount].
586 m_uiPort == RemoteAddr.sin_port)) {
587 break;
590 if ((pInstance->m_aSdoAbsUdpConnection[iCount].
591 m_ulIpAddr == 0)
592 && (pInstance->
593 m_aSdoAbsUdpConnection[iCount].
594 m_uiPort == 0)
595 && (iFreeEntry == 0xFFFF))
597 iFreeEntry = iCount;
600 iCount++;
603 if (iCount == EPL_SDO_MAX_CONNECTION_UDP) {
604 // connection unknown
605 // see if there is a free handle
606 if (iFreeEntry != 0xFFFF) {
607 // save adress infos
608 pInstance->
609 m_aSdoAbsUdpConnection[iFreeEntry].
610 m_ulIpAddr =
611 RemoteAddr.sin_addr.s_addr;
612 pInstance->
613 m_aSdoAbsUdpConnection[iFreeEntry].
614 m_uiPort = RemoteAddr.sin_port;
615 // call callback
616 SdoConHdl = iFreeEntry;
617 SdoConHdl |= EPL_SDO_UDP_HANDLE;
618 // offset 4 -> start of SDO Sequence header
619 pInstance->m_fpSdoAsySeqCb(SdoConHdl,
620 (tEplAsySdoSeq
621 *) &
622 abBuffer[4],
623 (iError -
624 4));
625 } else {
626 EPL_DBGLVL_SDO_TRACE0
627 ("Error in EplSdoUdpThread() no free handle\n");
630 } else {
631 // known connection
632 // call callback with correct handle
633 SdoConHdl = iCount;
634 SdoConHdl |= EPL_SDO_UDP_HANDLE;
635 // offset 4 -> start of SDO Sequence header
636 pInstance->m_fpSdoAsySeqCb(SdoConHdl,
637 (tEplAsySdoSeq *) &
638 abBuffer[4],
639 (iError - 4));
641 } // end of if(iError!=SOCKET_ERROR)
642 } // end of for(;;)
644 complete_and_exit(&SdoUdpInstance_g.m_CompletionUdpThread, 0);
645 return 0;
648 #endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
650 // EOF