diff gpf/tst/DRV/socket.c @ 0:509db1a7b7b8

initial import: leo2moko-r1
author Space Falcon <falcon@ivan.Harhan.ORG>
date Mon, 01 Jun 2015 03:24:05 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gpf/tst/DRV/socket.c	Mon Jun 01 03:24:05 2015 +0000
@@ -0,0 +1,1896 @@
+/* 
++------------------------------------------------------------------------------
+|  File:       socket.c
++------------------------------------------------------------------------------
+|  Copyright 2002 Texas Instruments Berlin, AG 
+|                 All rights reserved. 
+| 
+|                 This file is confidential and a trade secret of Texas 
+|                 Instruments Berlin, AG 
+|                 The receipt of or possession of this file does not convey 
+|                 any rights to reproduce or disclose its contents or to 
+|                 manufacture, use, or sell anything it may describe, in 
+|                 whole, or in part, without the specific written consent of 
+|                 Texas Instruments Berlin, AG. 
++----------------------------------------------------------------------------- 
+|  Purpose :  This Modul contains the socket driver adaptation
++----------------------------------------------------------------------------- 
+*/ 
+
+#ifdef _VXWORKS_
+#define GNU_COMPILER
+#endif
+
+#undef SOCK_TRACE
+
+#undef SOCKET_DEBUG
+
+/*==== INCLUDES =============================================================*/
+
+#if defined _NUCLEUS_ || defined _TOOLS_   /* socket-driver running on windows OS */
+/*lint -e717 suppress info do...while(0); */
+/*lint -esym(550,rc) suppress info not accessed */
+/*lint -e813, suppress Info 813: auto variable has size > 100 -> uncritical in this context */
+/*lint -e801, suppress Info 801: Use of goto is deprecated */
+  #include <windows.h>
+  #include <winsock.h>
+  #include <stdio.h>
+  #ifdef SOCK_TRACE
+    #include <stdio.h>
+    #include <fcntl.h>
+    #include <io.h>
+  #endif  /* SOCK_TRACE */
+#endif  /* #ifdef _NUCLEUS_ */
+
+#ifdef _PSOS_                /* socket-driver running on pSOS */
+  #define _PNA_30_BACK
+  #include <psos.h>
+  #include "bsp.h"
+  #include <pna.h>
+  #include <prepc.h>
+  #include <rescfg.h>
+#endif /* #ifdef _PSOS_ */
+
+#ifdef _VXWORKS_
+  #include "vxWorks.h"
+  #include "sockLib.h"
+  #include "inetLib.h"
+  #include "ioLib.h"
+  #include "selectLib.h"
+  #include "errnoLib.h"
+  #include "logLib.h"
+/* undefine the MALLOC and FREE of VxWorks to avoid warnings */
+#undef MALLOC
+#undef FREE
+#endif  /* _VXWORKS_ */
+
+/* More operating systems go here */
+
+#ifdef _LINUX_
+  #include <sys/types.h>
+  #include <sys/socket.h>
+  #include <netinet/in.h>
+  #include <netinet/tcp.h>
+  #include <sys/ioctl.h>
+  #include <errno.h>
+  #include <netdb.h>
+#endif
+
+#ifdef _SOLARIS_
+  #include <sys/types.h>
+  #include <sys/socket.h>
+  #include <netinet/in.h>
+  #include <netinet/tcp.h>
+  #include <sys/ioctl.h>
+  #include <errno.h>
+  #include <netdb.h>
+  #include <sys/filio.h>
+#endif
+
+#ifndef OLD_FRAME
+  #include "typedefs.h"
+  #include "os.h"
+#endif
+
+#include "socket.h"
+#include "tools.h"
+#include "vsi.h"
+#include "drvconf.h"
+#include "tstheader.h"
+
+/*==== DEFINITIONS ==========================================================*/
+
+#define MAX_PENDING_CONNECTS  5          /* The backlog allowed for listen() */
+#define SEND_TIMEOUTUSEC      500        /* minimal timeout value for sending*/
+#define INVALID_HANDLE        NULL
+#define INVALID_SIGNALTYPE    0
+#define NO_FLAGS_SET          0          /* Used with recv()/send()          */
+#define MAX_ETH_LEN           (1500-40)  /* Maximum size of a Ethernet packet without IP headers */
+#define WRBUF_LEN             2048
+
+#define ALLOWED_SOCKET_SIGNALS   (DRV_SIGTYPE_READ|DRV_SIGTYPE_CONNECT|DRV_SIGTYPE_DISCONNECT)
+
+#if defined _NUCLEUS_ || defined _TOOLS_
+    typedef ULONG SIZETYPE;
+    #define GETTIME(t)           (t = GetTickCount())
+    #define GETREADSIZE(sok,psiz) ioctlsocket(sok, FIONREAD,(ULONG*)psiz)
+    #define READ_SOCKET(s,b,l)    recv((s),(b),(int)(l),NO_FLAGS_SET)
+    #define WRITE_SOCKET(s,b,l)   send((s),(const char*)(b),(l),NO_FLAGS_SET)
+    #define CLOSE_SOCKET(s)       closesocket(s)
+#endif /* #ifdef _NUCLEUS_ */
+
+#ifdef _PSOS_
+  typedef int SOCKET;
+  typedef int SIZETYPE;
+  typedef struct hostent HOSTENT;
+  #define h_addr  h_addr_list[0]
+  typedef HOSTENT *  PHOSTENT;
+  #define FAR /**/
+  #define SOCKADDR_IN struct sockaddr_in
+  #define SOCKET_ERROR   (-1)
+  #define INVALID_SOCKET (-1)
+  #define GETTIME(t)            os_GetTime (0, &(t))
+  #define GETREADSIZE(sok,psiz) ioctl(sok, FIOREAD,(char*)psiz)
+  #define READ_SOCKET(s,b,l)    recv((s),(b),(int)(l),NO_FLAGS_SET)
+  #define WRITE_SOCKET(s,b,l)   send((s),(char *)(b),(int)(l),NO_FLAGS_SET)
+  #define CLOSE_SOCKET(s)       close(s)
+#endif /* #ifdef _PSOS_ */
+
+#ifdef _VXWORKS_
+  #define SOCKADDR_IN    struct sockaddr_in
+  #define FAR /* nil */
+  #define SOCKET_ERROR   ERROR
+  #define INVALID_SOCKET ERROR
+  typedef int SOCKET;
+  typedef int SIZETYPE;
+  #define GETTIME(t)            os_GetTime (0, &(t))
+  #define GETREADSIZE(sok,psiz) ioctl(sok, FIONREAD, (int)psiz)
+  #define READ_SOCKET(s,b,l)    recv((s), (b), (int)(l), NO_FLAGS_SET)
+  #define WRITE_SOCKET(s,b,l)   send((s), (char *)(b), (int)(l), NO_FLAGS_SET)
+  #define CLOSE_SOCKET(s)       close(s)
+#endif /* _VXWORKS_ */
+
+#if defined (_LINUX_) || defined (_SOLARIS_)
+  #define SOCKADDR_IN    struct sockaddr_in
+  #define FAR /* nil */
+  #define SOCKET_ERROR   (-1)
+  #define INVALID_SOCKET (-1)
+  typedef int SIZETYPE;
+  #define GETTIME(t)            os_GetTime (0, &(t))
+  #define GETREADSIZE(sok,psiz) ioctl(sok, FIONREAD, (int)psiz)
+  #define READ_SOCKET(s,b,l)    recv((s), (b), (int)(l), NO_FLAGS_SET)
+  #define WRITE_SOCKET(s,b,l)   send((s), (char *)(b), (int)(l), NO_FLAGS_SET)
+  #define CLOSE_SOCKET(s)       close(s)
+#endif /* _VXWORKS_ */
+
+#define PORT_NO              6392
+#define TX_BUFFER_SIZE       8192
+#define RX_BUFFER_SIZE       8192
+#define TX_TIMEOUT_MSEC     10000
+#define RX_TIMEOUT_MSEC     10000
+
+#ifdef _VXWORKS_
+#define SOCKET_PRIO    115
+#define SOCKET_STACK  8192
+#elif defined _PSOS_
+#define SOCKET_PRIO    110
+#define SOCKET_STACK  1024
+#elif defined _TOOLS_
+#define SOCKET_PRIO      1
+#define SOCKET_STACK  1024
+#else
+#define SOCKET_PRIO      1
+#define SOCKET_STACK  1024
+#endif
+
+#define TI_MODE     0x0001
+
+/*==== TYPES ================================================================*/
+typedef enum
+{
+  SST_PL0,     /* 0 bytes of packet length read*/
+  SST_PL1,     /* 1 bytes of packet length read*/
+  SST_DATA0,   /* 0 bytes of data read*/
+  SST_DATAx    /* not all data read */
+} T_SOCK_STATE;
+
+typedef struct
+{
+  USHORT            Connect;
+  SOCKET            Listener;
+  SOCKET            Socket;
+  USHORT            EnabledSignals;
+  OS_HANDLE         ThreadID ;
+  USHORT            SocketHandle;
+  T_DRV_CB_FUNC     Callback;
+} Client_Type;
+
+/*==== EXTERNALS ============================================================*/
+EXTERN BOOL           socket_flush;
+
+/*==== LOCAL VARS ===========================================================*/
+
+LOCAL socket_DCB_Type L_DCB ;
+LOCAL Client_Type     L_ClientData ;
+LOCAL BOOL            L_ThreadActive ;
+LOCAL T_DRV_SIGNAL    SocketSignal;
+LOCAL UBYTE    wrbuf[WRBUF_LEN+2];
+LOCAL UBYTE   *wrbuf_pos = wrbuf;
+T_SOCK_STATE   sock_state = SST_PL0;
+
+#ifdef SOCK_TRACE
+ULONG                 fh_sock = -1;
+LOCAL char            stbuf[80];
+#endif
+
+LOCAL BOOL     isLittleEndian = TRUE;
+int tst_socket; /* for psos */
+int tst_socket_initialized; /* flag for pSOS */
+int tst_socket_in_TxLen;    /* for pSOS */
+
+
+/*==== DIAGNOSTICS ==========================================================*/
+
+#ifdef SOCKET_DEBUG
+#include <STDIO.H>
+static char *logfile = "socket.log";
+static char *bufferfullfile = "bufferfull.log";
+static char *inprocessfile = "inprogress.log";
+static char *noconnectfile1 = "noconnect1.log";
+static char *noconnectfile2 = "noconnect2.log";
+static char *noconnectfile3 = "noconnect3.log";
+static char *readerrorfile = "readerror.log";
+static FILE *fp = NULL;
+#endif /* SOCKET_DEBUG */
+
+/*==== END DIAGNOSTICS ======================================================*/
+
+extern USHORT ext_data_pool_handle;
+
+GLOBAL ULONG drv_socket_task_stack_size = SOCKET_STACK;
+GLOBAL USHORT drv_socket_task_prio = SOCKET_PRIO;
+
+/*==== PRIVATE FUNCTIONS ====================================================*/
+/*
++------------------------------------------------------------------------------
+|  Function    : L_CreateThread
++------------------------------------------------------------------------------
+|  Description : This function creates a thread.
+|
+|  Parameters  : ThreadFunc        - pointer to the function beeing a thread
+|
+|  Return      : FALSE             - Thread not created
+|                TRUE              - Thread create (Thread ID stored in
+|                                    L_ClientData.ThreadID
+|
++------------------------------------------------------------------------------
+*/
+#ifdef OLD_FRAME
+BOOL L_CreateThread (USHORT (*ThreadFunc)(USHORT,ULONG))
+{
+  return (CreateThread ((LPSECURITY_ATTRIBUTES) NULL,
+                0,
+                (LPTHREAD_START_ROUTINE)ThreadFunc,
+                (LPVOID) NULL,
+                0,
+                &L_ClientData.ThreadID) != NULL);
+}
+#else
+BOOL L_CreateThread (void (*ThreadFunc)(T_HANDLE,ULONG))
+{
+  if ( os_CreateTask (0, (char*)"SOCKET", ThreadFunc, drv_socket_task_stack_size, drv_socket_task_prio, &L_ClientData.ThreadID, ext_data_pool_handle) < 0L )
+    return FALSE;
+  if ( os_StartTask (0, L_ClientData.ThreadID, 0) < 0 )
+    return FALSE ;
+
+  return TRUE;
+}
+#endif
+
+/*
++------------------------------------------------------------------------------
+|  Function    : L_SetSocketBuffer
++------------------------------------------------------------------------------
+|  Description : This function sets the IP read and write buffer
+|
+|  Parameters  : in_TxLen          - size of transmission buffer
+|                in_RxLen          - size of receiver buffer
+|
+|  Return      : FALSE             - either the read or write buffer could not
+|                                    be set.
+|                TRUE              - OK
+|
++------------------------------------------------------------------------------
+*/
+LOCAL BOOL L_SetSocketBuffer (USHORT  in_TxLen, USHORT in_RxLen)
+{
+  int in_TxLen1 = (int) in_TxLen;
+  int in_RxLen1 = (int) in_RxLen;
+#ifndef _PSOS_
+  int nodelay = TRUE;
+#if defined (_VXWORKS_) || defined (_LINUX_) || defined (_SOLARIS_)
+  struct linger nolinger = {0, 0};
+#else
+  int linger = TRUE;
+#endif
+  int rc=0;
+
+  if (in_TxLen > 0)
+  {
+    if ( (rc=setsockopt(L_ClientData.Socket, SOL_SOCKET, SO_SNDBUF,
+                   (char*)&in_TxLen1, sizeof(in_TxLen1))) != 0)
+    {
+#ifdef _VXWORKS_
+      rc = errnoGet ();
+#else
+  #if defined (_LINUX_) || defined (_SOLARIS_)
+      rc = errno;
+  #else
+      rc = WSAGetLastError();
+  #endif
+#endif
+#if defined _NUCLEUS_ || defined _TOOLS_
+      printf("SOCKET: setsockopt() returned error code %d\n", rc); 
+#endif
+      return FALSE ;
+    }
+  }
+#if defined (_VXWORKS_) || defined (_LINUX_) || defined (_SOLARIS_)
+  if (setsockopt(L_ClientData.Socket, SOL_SOCKET, SO_LINGER,
+               (char*)&nolinger, sizeof(nolinger)))
+#else
+  if (setsockopt(L_ClientData.Socket, SOL_SOCKET, (int)SO_DONTLINGER,
+               (char*)&linger, sizeof(linger)))
+#endif
+    return FALSE ;
+  if (setsockopt(L_ClientData.Socket, IPPROTO_TCP, TCP_NODELAY,
+               (char*)&nodelay, sizeof(nodelay)))
+    return FALSE ;
+
+#else /* PSOS */
+  tst_socket_in_TxLen = in_TxLen;
+#endif /* PSOS */
+  if (in_RxLen > 0)
+  {
+    if (setsockopt(L_ClientData.Socket, SOL_SOCKET, SO_RCVBUF,
+                   (char *) &in_RxLen1, sizeof(in_RxLen1)))
+      return FALSE ;
+  }
+
+  return TRUE ;
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function    : L_Disconnect
++------------------------------------------------------------------------------
+|  Description : This function is called when the connection to the peer entity
+|                is lost. If the release signal is set a signal is generated.
+|
+|  Parameters  :  -
+|
+|  Return      :  -
+|
++------------------------------------------------------------------------------
+*/
+LOCAL void L_Disconnect (void)
+{
+
+  L_ClientData.Connect = FALSE;
+  if (L_ClientData.EnabledSignals != INVALID_SIGNALTYPE)
+  {
+    SocketSignal.SignalType = DRV_SIGTYPE_DISCONNECT;
+    SocketSignal.DrvHandle = L_ClientData.SocketHandle;
+    (*L_ClientData.Callback)(&SocketSignal) ;
+  }
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function    : L_AsyncSelect
++------------------------------------------------------------------------------
+|  Description : This function waits (blocking) for either something to read
+|                or an execption on the socket.
+|
+|  Parameters  : -
+|
+|  Return      : FALSE             - failure on the socket
+|                TRUE              - a read event was signalled
+|
++------------------------------------------------------------------------------
+*/
+LOCAL BOOL L_AsyncSelect (void)
+{
+  fd_set  fd_r ;
+  fd_set  fd_e ;
+  int     status, rc;
+
+  /* wait for possibility to read */
+  FD_ZERO(&fd_r);
+  FD_SET(L_ClientData.Socket, &fd_r);
+  FD_ZERO(&fd_e);
+  FD_SET(L_ClientData.Socket, &fd_e);
+
+  status = select(FD_SETSIZE, &fd_r, NULL, &fd_e, (struct timeval *) 0);
+
+  if (status > 0)
+  {
+    if (!FD_ISSET (L_ClientData.Socket, &fd_e))
+    {
+      if (L_ClientData.Callback != NULL)
+      {
+        if (FD_ISSET (L_ClientData.Socket, &fd_r))
+        {
+          SIZETYPE size ;
+
+          if ((rc = GETREADSIZE( L_ClientData.Socket, &size)) != 0 || !size)
+          {
+#ifdef SOCK_TRACE
+            if (fh_sock != -1)
+            {
+              char sstop[10];
+              ULONG stop = GetTickCount();
+
+              sprintf(sstop, "%03d:%03d",  (stop/1000) % 1000, stop % 1000);
+              sprintf(stbuf, "reset at %s rc=%d size=%d left %d \n",
+                              sstop, rc, size,
+                              wrbuf_pos-wrbuf);
+              write (fh_sock, stbuf, strlen(stbuf));
+/*              close(fh_sock);
+              fh_sock = -1; */
+            }
+#endif
+            os_SuspendTask ( 0, 2 );
+            CLOSE_SOCKET (L_ClientData.Socket);
+            L_ClientData.Socket = INVALID_SOCKET;
+            wrbuf_pos = wrbuf;
+            sock_state = SST_PL0;
+            return FALSE ;
+          }
+
+          /* Indicate that it is possible to read something */
+          if (L_ClientData.EnabledSignals & DRV_SIGTYPE_READ)
+          {
+            SocketSignal.SignalType = DRV_SIGTYPE_READ;
+            SocketSignal.DrvHandle = L_ClientData.SocketHandle;
+            (*L_ClientData.Callback)(&SocketSignal) ;
+          }
+        }
+      }
+      return TRUE ;
+    }
+  }
+  return FALSE;
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function    : L_ClientThread
++------------------------------------------------------------------------------
+|  Description : This function is a thread used if the driver is configured to
+|                be a client.
+|
+|  Parameters  : -
+|
+|  Return      : -
+|
++------------------------------------------------------------------------------
+*/
+void L_ClientThread (T_HANDLE Handle, ULONG Value )
+{
+  L_ThreadActive = TRUE ;
+
+  L_SetSocketBuffer (L_DCB.tx_buffer_size, L_DCB.rx_buffer_size) ;
+
+  /*-------------------------------------
+    Listen what's goning on on the socket
+    -------------------------------------*/
+  while (L_ThreadActive)
+    if (!L_AsyncSelect())
+    {
+      L_ThreadActive = FALSE ;
+      L_Disconnect() ;
+    }
+}
+
+
+/*
++------------------------------------------------------------------------------
+|  Function    : L_ServerThread
++------------------------------------------------------------------------------
+|  Description : This function is a thread used if the driver is configured to
+|                be a server. It serves only one client. It cycles between
+|                two modes, wait for a client to connect and listening on the
+|                connection for any further action.
+|                The thread exits when the flag L_ThreadActive is set to false.
+|
+|  Parameters  : -
+|
+|  Return      : -
+|
++------------------------------------------------------------------------------
+*/
+void L_ServerThread (T_HANDLE TaskHandle, ULONG Value)
+{
+  BOOL BufferSizeSet;
+  SOCKADDR_IN local_sin;                      /* Local socket - internet style */
+#ifdef _VXWORKS_
+  SOCKADDR_IN clientAddr;                     /* client */
+  int sockAddrSize = sizeof (struct sockaddr_in);
+
+  memset ((char *) &local_sin, 0, sockAddrSize);
+  local_sin.sin_len = (u_char) sockAddrSize;
+#endif/* _VXWORKS_ */
+  L_ClientData.Listener = socket (AF_INET, SOCK_STREAM, 0);
+  if (L_ClientData.Listener == INVALID_SOCKET)
+    goto error;
+
+  if (L_DCB.port == SOCKET_INVALID_PORT)
+    goto error;
+
+  local_sin.sin_addr.s_addr = htonl(INADDR_ANY);
+  local_sin.sin_family = AF_INET;
+  local_sin.sin_port = htons(L_DCB.port);      /* Convert to network ordering */
+
+  /*-------------------------------------------
+    Associate an address with a socket. (bind)
+    -------------------------------------------*/
+#ifdef _PSOS_
+  if (bind (L_ClientData.Listener, (struct sockaddr_in*) &local_sin, sizeof(local_sin)) != 0)
+#else
+#ifdef _VXWORKS_
+  /* Look at the following cast of local_sin.
+   * This is from VxWorks Network 5.4 Programmer’s Guide, example 7-1, page 131
+   */
+  if (bind (L_ClientData.Listener, (struct sockaddr*) &local_sin, sockAddrSize) == ERROR)
+#else /* _VXWORKS_ */
+  if (bind (L_ClientData.Listener, (const struct sockaddr FAR *) &local_sin, sizeof(local_sin)) != 0)
+#endif /* _VXWORKS_ */
+#endif
+  {
+    CLOSE_SOCKET (L_ClientData.Listener);
+    goto error;
+  }
+#ifdef _VXWORKS_
+  if (listen (L_ClientData.Listener, MAX_PENDING_CONNECTS) == ERROR)
+#else /* _VXWORKS_ */
+  if (listen (L_ClientData.Listener, MAX_PENDING_CONNECTS) != 0)
+#endif /* _VXWORKS_ */
+  {
+    CLOSE_SOCKET (L_ClientData.Listener);
+    goto error;
+  }
+
+  BufferSizeSet = FALSE ;
+  L_ThreadActive = TRUE ;
+
+  while (L_ThreadActive)
+  {
+    /*-------------------------------------
+      Wait for somebody to connect
+      -------------------------------------*/
+    if (L_ClientData.Socket != INVALID_SOCKET)
+    {
+#ifdef SOCK_TRACE
+      if (fh_sock != -1)
+      {
+        char sstop[10];
+        ULONG stop = GetTickCount();
+
+        sprintf(sstop, "%03d:%03d",  (stop/1000) % 1000, stop % 1000);
+        sprintf(stbuf, "close at %s socket=%d\n",
+                        sstop, L_ClientData.Socket);
+        write (fh_sock, stbuf, strlen(stbuf));
+/*      close(fh_sock);
+        fh_sock = -1;   */
+      }
+#endif
+      CLOSE_SOCKET (L_ClientData.Socket);
+      L_ClientData.Socket = INVALID_SOCKET;
+      wrbuf_pos = wrbuf;
+      sock_state = SST_PL0;
+    }
+#ifdef _VXWORKS_
+    if ((L_ClientData.Socket = accept (L_ClientData.Listener,
+                                       (struct sockaddr *) &clientAddr,
+                                       &sockAddrSize)) != ERROR)
+#else /* _VXWORKS_ */
+    L_ClientData.Socket = accept(L_ClientData.Listener, NULL, NULL) ;
+    if (L_ClientData.Socket != INVALID_SOCKET)
+#endif /* _VXWORKS_ */
+    {
+#ifdef SOCK_TRACE
+      if (fh_sock == -1)
+        fh_sock = open("SOCK_S.dbg", O_WRONLY| O_TEXT| O_TRUNC| O_CREAT, 0666);
+      if (fh_sock != -1)
+      {
+        char sstop[10];
+        ULONG stop = GetTickCount();
+
+        sprintf(sstop, "%03d:%03d",  (stop/1000) % 1000, stop % 1000);
+        sprintf(stbuf, "accept at %s socket=%d listener=%d\n",
+                        sstop, L_ClientData.Socket, L_ClientData.Listener);
+        write (fh_sock, stbuf, strlen(stbuf));
+      }
+#endif
+
+#ifdef _PSOS_
+      {
+        ULONG tid;
+        int err;
+        /* for pSOS */
+        /* wait for TST task */
+        while( t_ident( FRM_TST_NAME, 0, &tid ) != 0 )
+          tm_wkafter( 10 );
+
+        tst_socket = shr_socket( L_ClientData.Socket, (int)tid );
+        if( tst_socket < 0 )
+        {
+          err = errno;
+          goto error;
+        }
+      }
+#endif
+
+      if (!BufferSizeSet)
+        L_SetSocketBuffer (L_DCB.tx_buffer_size, L_DCB.rx_buffer_size) ;
+
+      /* Signalisiere Connect */
+      L_ClientData.Connect = TRUE;
+      if (L_ClientData.EnabledSignals & DRV_SIGTYPE_CONNECT)
+      {
+        SocketSignal.SignalType = DRV_SIGTYPE_CONNECT;
+        SocketSignal.DrvHandle = L_ClientData.SocketHandle;
+        (*L_ClientData.Callback)(&SocketSignal) ;
+      }
+
+      /*-------------------------------------
+        Listen what's goning on on the socket
+        -------------------------------------*/
+      while (L_ThreadActive)
+        if (!L_AsyncSelect())
+        {
+          L_Disconnect() ;
+          break ;
+        }
+    }
+  }
+
+error:
+#ifndef OLD_FRAME
+  for(;;)
+    os_SuspendTask( 0, 1000 );
+#endif
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function    : socket_Create
++------------------------------------------------------------------------------
+|  Description : This function is used to set up the driver to act as a
+|                server. The function tries to initialize the socket, creates
+|                a thread in which it awaits first awaits the establishement
+|                of a connection by a client. As soon as a client has
+|                connected a signal (SOCKET_CONNECTED) is generated (call
+|                socket_SetSignal() to activate a signal). From this time the
+|                driver is able to send data (socket_write()) to the client and
+|                to read received data (socket_read()). To get notified about
+|                the reception of data the apropriate signal has to be set.
+|                In the case of a successful completion the driver returns
+|                DRV_OK.
+|                If the driver is already busy DRV_INPROCESS is returned.
+|                If the driver is not configured, the function returns
+|                DRV_ NOTCONFIGURED.
+|
+|  Parameters  : -
+|
+|  Return      : DRV_OK             - Function successful
+|                DRV_INPROCESS      - The driver is currently reading data.
+|                                     The data is incomplete.
+|                DRV_NOTCONFIGURED  - The driver is not yet configured
+|                SOCKET_ERRORUNSPEC - Error occured during initialization
+|
++------------------------------------------------------------------------------
+*/
+LOCAL UBYTE L_CreateServer (void)
+{
+  if (!L_CreateThread (L_ServerThread))
+  {
+    CLOSE_SOCKET (L_ClientData.Listener);
+    return SOCKET_ERRUNSPEC;
+  }
+#ifdef _TOOLS_
+  printf("SOCKET: now listening on port %i ...\n",L_DCB.port); 
+#endif
+
+  return DRV_OK ;
+}
+/*
++------------------------------------------------------------------------------
+| Function    : socket_WriteToOS
++------------------------------------------------------------------------------
+| Description : This function is used to write data to the driver of operating
+|               system.
+|               The parameter thr_BufferSize contains the number of
+|               characters to write. In the case of a successful completion,
+|               the function returns DRV_OK.
+|
+| Parameters  : in_BufferPtr          - This parameter points to the buffer
+|                                       that is passed to the driver for
+|                                       further processing
+|               thr_BufferSize        - number of characters to write.
+|
+| Return      : DRV_OK            - Function successful
+|               DRV_INPROCESS     - Driver is busy writing data
+|               SOCKET_NOCONNECT  - Connection not available
+|
++------------------------------------------------------------------------------
+*/
+LOCAL UBYTE socket_WriteToOS (void*  in_BufferPtr, USHORT thr_BufferSize)
+{
+  int             err;
+  USHORT          c_written;
+#ifndef _PSOS_
+  fd_set          fd_w;
+  fd_set          fd_e;
+  struct timeval  tv;
+
+  if (L_ClientData.Socket == INVALID_SOCKET)
+    return SOCKET_NOCONNECT;
+
+  if ( L_ClientData.Connect == FALSE )
+    return SOCKET_NOCONNECT ;
+
+  tv.tv_sec = (int)(L_DCB.tx_timeout_msec / 1000) ;
+  tv.tv_usec = SEND_TIMEOUTUSEC ;
+
+  FD_ZERO(&fd_w);
+  FD_SET(L_ClientData.Socket, &fd_w);
+  FD_ZERO(&fd_e);
+  FD_SET(L_ClientData.Socket, &fd_e);
+
+  if (select(FD_SETSIZE, NULL, &fd_w, &fd_e, &tv) <= 0)
+  {
+#ifdef SOCKET_DEBUG
+    char buffer[200];
+    char *ptr = in_BufferPtr;
+    char c = ptr[21];
+    fp = fopen(inprocessfile, "at");
+    if ( *ptr == 'P' )
+      ptr[21] = 0;
+    else
+      ptr[thr_BufferSize] = 0;
+    strcpy (buffer, "errno:" );    
+    sprintf (&buffer[6], "%8d", WSAGetLastError() );
+    buffer[14] = ' ';
+    memcpy (&buffer[15], ptr, (thr_BufferSize)+1);
+    fprintf (fp, "%s\n", buffer );
+    ptr[21] = c;
+    fclose(fp);
+#endif  /* SOCKET_DEBUG */
+#ifdef _VXWORKS_
+    err = errnoGet ();
+#else /* _VXWORKS_ */
+    err = errno;
+    printf("SOCKET: socket write failed with error code: %d\n",err );
+#endif /* _VXWORKS_ */
+
+    return DRV_INPROCESS ;
+  }
+
+  if (FD_ISSET (L_ClientData.Socket, &fd_e))
+  {
+#ifdef SOCKET_DEBUG
+    char buffer[200];
+    char *ptr = in_BufferPtr;
+    char c = ptr[21];
+    fp = fopen(noconnectfile1, "at");
+    if ( *ptr == 'P' )
+      ptr[21] = 0;
+    else
+      ptr[thr_BufferSize] = 0;
+    strcpy (buffer, "errno:" );
+    sprintf (&buffer[6], "%8d", WSAGetLastError() );
+    buffer[14] = ' ';
+    memcpy (&buffer[15], ptr, (thr_BufferSize)+1);
+    fprintf (fp, "%s\n", buffer );
+    ptr[21] = c;
+    fclose(fp);
+#endif  /* SOCKET_DEBUG */
+    return SOCKET_NOCONNECT ;
+  }
+
+  /*---------------------------------
+    Send the data
+    ---------------------------------*/
+  c_written = (USHORT) WRITE_SOCKET(L_ClientData.Socket, in_BufferPtr, (USHORT)thr_BufferSize);
+
+  if (c_written == (USHORT)SOCKET_ERROR || c_written != thr_BufferSize)
+  {
+#ifdef SOCKET_DEBUG
+    char buffer[200];
+    char *ptr = in_BufferPtr;
+    char c = ptr[21];
+    fp = fopen(noconnectfile2, "at");
+    if ( *ptr == 'P' )
+      ptr[21] = 0;
+    else
+      ptr[thr_BufferSize] = 0;
+    strcpy (buffer, "errno:" );
+    sprintf (&buffer[6], "%8d", WSAGetLastError() );
+    buffer[14] = ' ';
+    memcpy (&buffer[15], ptr, (thr_BufferSize)+1);
+    fprintf (fp, "%s\n", buffer );
+    ptr[21] = c;
+    fclose(fp);
+#endif  /* SOCKET_DEBUG */
+    return SOCKET_NOCONNECT ;
+  }
+
+#ifdef SOCK_TRACE
+  if (fh_sock != -1)
+  {
+    char sstop[10];
+    ULONG stop = GetTickCount();
+
+    sprintf(sstop, "%03d:%03d",  (stop/1000) % 1000, stop % 1000);
+    sprintf(stbuf, "sent %d at %s\n",
+                 thr_BufferSize,
+                 sstop);
+    write (fh_sock, stbuf, strlen(stbuf));
+  }
+#endif
+  return DRV_OK ;
+
+#else
+
+  /* pSOS */
+
+  /*---------------------------------
+    Send the data
+    ---------------------------------*/
+  c_written = (USHORT) WRITE_SOCKET(tst_socket, in_BufferPtr, (USHORT)thr_BufferSize);
+
+  if (c_written == (USHORT)SOCKET_ERROR || c_written != thr_BufferSize)
+  {
+    err = errno;
+    return SOCKET_NOCONNECT ;
+  }
+
+  return DRV_OK ;
+#endif  /* _PSOS_ */
+}
+
+/*==== PUBLIC FUNCTIONS =====================================================*/
+
+/*
++------------------------------------------------------------------------------
+|  Function    : socket_Exit
++------------------------------------------------------------------------------
+|  Description : The function is called when the driver functionality is no
+|                longer required. The function "de-allocates" the resources
+|                and releases active connections. The driver terminates
+|                regardless of any outstanding data to be sent.
+|
+|  Parameters  : -
+|
+|  Return      : -
+|
++------------------------------------------------------------------------------
+*/
+void socket_Exit (void)
+{
+  os_DestroyTask ( 0, L_ClientData.ThreadID );
+  socket_Close() ;
+}
+
+
+/*
++------------------------------------------------------------------------------
+|  Function    : socket_Open
++------------------------------------------------------------------------------
+|  Description : This function is used to establish a connection to server or
+|                activate the driver to act as a server, using the settings of
+|                the socket_DCB. A hostname must be specified to open a
+|                connection to a server, in this case the driver runs in the
+|                client mode. If no hostname is specified the driver will run in
+|                server mode. In the server mode it serves a single client. As
+|                soon as a client is connected the CONNECT signal is generated.
+|                In case of a successful completion the driver is no able to send
+|                data (socket_write()) to the peer entity and to read data
+|                received from the peer entity (socket_read()). To get notified
+|                about the reception of data the appropriate signal has to be set
+|                (socket_SetSignal()).
+|                In the case of a successful completion the driver returns DRV_OK.
+|                If the driver is already busy DRV_INPROCESS is returned.
+|                If the driver is not configured, the function returns
+|                DRV_NOTCONFIGURED.
+|                If an error occurs while establishing the requested mode, the
+|                function returns SOCKET_ERRUNSPEC.
+|
+|  Parameters  : -
+|
+|  Return      : DRV_OK            - Function successful
+|                DRV_INPROCESS     - The driver is currently reading data.
+|                                    The data is incomplete.
+|                DRV_NOTCONFIGURED - The driver is not yet configured
+|                SOCKET_ERRUNSPEC  - Error occured during initialization
+|
++------------------------------------------------------------------------------
+*/
+USHORT socket_Open (void)
+{
+  SOCKADDR_IN dest_sin;  /* DESTination Socket INternet */
+  SOCKET      connectsocket;
+#ifdef _VXWORKS_
+  int sockAddrSize;
+#else /* _VXWORKS_ */
+  #if defined (_LINUX_) || defined (_SOLARIS_)
+    struct hostent* phe;
+  #else
+    PHOSTENT    phe;
+  #endif
+#endif /* _VXWORKS_ */
+  if (L_ThreadActive)
+  {
+    return DRV_INPROCESS ;
+  }
+
+  /*---------------------------------
+    if no hostname is specified we
+    open as a server
+    ---------------------------------*/
+  if (!*L_DCB.hostname)
+  {
+    return L_CreateServer() ;
+  }
+
+  connectsocket = socket (AF_INET, SOCK_STREAM, 0);
+  if (connectsocket == INVALID_SOCKET)
+  {
+    return SOCKET_ERRUNSPEC;
+  }
+
+#ifdef _PSOS_
+
+  if ( !gethostbyname(L_DCB.hostname, phe))
+  {
+    CLOSE_SOCKET(connectsocket);
+    return SOCKET_ERRUNSPEC;
+  }
+
+#else /* _PSOS_ */
+  #ifdef _VXWORKS_
+    sockAddrSize = sizeof (struct sockaddr_in);
+    memset((char *) &dest_sin, 0, sockAddrSize);
+    dest_sin.sin_len = (u_char) sockAddrSize;
+    dest_sin.sin_family = AF_INET;
+    dest_sin.sin_port = htons(L_DCB.port);
+    if (((dest_sin.sin_addr.s_addr = inet_addr (L_DCB.hostname)) == ERROR) &&
+    ((dest_sin.sin_addr.s_addr = hostGetByName (L_DCB.hostname)) == ERROR))
+    {
+      CLOSE_SOCKET(connectsocket);
+      return SOCKET_ERRUNSPEC;
+    }
+  #else /* _VXWORKS_ */
+  phe = gethostbyname(L_DCB.hostname);
+  if (!phe)
+  {
+#ifdef _TOOLS_
+    printf("SOCKET: host %s not found ;-(\n",L_DCB.hostname); 
+#endif
+    CLOSE_SOCKET(connectsocket);
+    return SOCKET_ERRUNSPEC;
+  }
+  #endif /* _VXWORKS_ */
+#endif  /* _PSOS_ */
+
+#ifndef _VXWORKS_
+  memset(&dest_sin, 0, sizeof(struct sockaddr_in));
+  memcpy((char*)&(dest_sin.sin_addr), phe->h_addr, (unsigned int)((int)(phe->h_length)));
+  dest_sin.sin_family = AF_INET;
+  if ( L_DCB.config & TI_MODE )
+    dest_sin.sin_port = L_DCB.port;
+  else
+    dest_sin.sin_port = htons(L_DCB.port);
+#endif /* _VXWORKS_ */
+
+#ifdef _PSOS_
+  if (connect (connectsocket, (struct sockaddr_in*) &dest_sin, sizeof(dest_sin)))
+#else /* _PSOS_ */
+  #ifdef _VXWORKS_
+  if (connect (connectsocket, (struct sockaddr*) &dest_sin, sockAddrSize) == ERROR)
+  #else /* _VXWORKS_ */
+    #if defined (_LINUX_) || defined (_SOLARIS_)
+      if (connect (connectsocket, (struct sockaddr*) &dest_sin,
+                   sizeof(dest_sin)))
+    #else
+      if (connect (connectsocket, (const PSOCKADDR) &dest_sin,
+                   sizeof(dest_sin)))
+    #endif
+  #endif /* _VXWORKS_ */
+#endif /* defined(_PSOS_) || defined(_VXWORKS_) */
+  {
+#ifdef _TOOLS_
+    printf("SOCKET: connection to %s on port %i failed ;-(\n",L_DCB.hostname,L_DCB.port); 
+#endif
+    CLOSE_SOCKET(connectsocket);
+    return SOCKET_ERRUNSPEC;
+  }
+#ifdef _TOOLS_
+  printf("SOCKET: successfully connected to %s on port %i\n",L_DCB.hostname,L_DCB.port); 
+#endif
+
+  if (!L_CreateThread (L_ClientThread))
+  {
+    CLOSE_SOCKET (L_ClientData.Listener);
+    return SOCKET_ERRUNSPEC;
+  }
+
+  L_ClientData.Socket = connectsocket ;
+  L_ClientData.Connect = TRUE;
+  if (L_ClientData.EnabledSignals & DRV_SIGTYPE_CONNECT)
+  {
+    SocketSignal.SignalType = DRV_SIGTYPE_CONNECT;
+    SocketSignal.DrvHandle = L_ClientData.SocketHandle;
+    (*L_ClientData.Callback)(&SocketSignal) ;
+  }
+  return DRV_OK ;
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function    : socket_Close
++------------------------------------------------------------------------------
+|  Description : This function is used by a client to close the connection or
+|                by server to shut down the server functionality.
+|                In case of a successful completion the connection is shutdown
+|                and neither socket_Read nor socket_Write will be successful.
+|                To get notified about the termination of a connection the
+|                appropriate signal has to be set (socket_SetSignal()).
+|
+|  Parameters  : -
+|
+|  Return      : -
+|
++------------------------------------------------------------------------------
+*/
+USHORT socket_Close (void)
+{
+  L_ThreadActive = FALSE ;
+
+#ifdef SOCK_TRACE
+  if (fh_sock != -1)
+  {
+    char sstop[10];
+    ULONG stop = GetTickCount();
+
+    sprintf(sstop, "%03d:%03d",  (stop/1000) % 1000, stop % 1000);
+    sprintf(stbuf, "socket_Close at %s socket=%d listener=%d\n",
+                    sstop, L_ClientData.Socket, L_ClientData.Listener);
+    write (fh_sock, stbuf, strlen(stbuf));
+  }
+#endif
+  if (L_ClientData.Socket != INVALID_SOCKET)
+  {
+    CLOSE_SOCKET (L_ClientData.Socket);
+    L_ClientData.Socket = INVALID_SOCKET;
+  }
+
+  if (L_ClientData.Listener != INVALID_SOCKET)
+    CLOSE_SOCKET (L_ClientData.Listener);
+
+  L_ClientData.ThreadID = 0 ;
+  return DRV_OK;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function    : socket_Read_with_Timeout
++------------------------------------------------------------------------------
+| Description : This function is used to read data from the USART driver.
+|               For more details see socket_Read()
+|
+| Return:       >= 0         - Number of bytes read
+|               SOCKET_ERROR - error occurred
++------------------------------------------------------------------------------
+*/
+LOCAL ULONG socket_Read_with_Timeout( void* destBuf, ULONG reqLen )
+{
+  ULONG timeout,
+        totalBytes = 0,
+        stop_timeout ;
+  int readBytes,
+        attempts = 0;
+
+  /* calculate timeout time */
+  GETTIME( stop_timeout );
+  stop_timeout = stop_timeout + L_DCB.rx_timeout_msec ;
+
+  /* read nonblocking until requested data is read or timeout */
+  do
+  {
+    readBytes = (SHORT)READ_SOCKET( L_ClientData.Socket,
+                                    ((char *)destBuf) + totalBytes,
+                                    reqLen - totalBytes );
+
+    if( readBytes < 0 || readBytes == SOCKET_ERROR )
+    {
+#ifdef SOCKET_DEBUG
+#ifndef _PSOS_
+      fp = fopen(readerrorfile, "at");
+      fprintf (fp, "WSAGetLastError returned: %8d", WSAGetLastError() );
+      fclose(fp);
+#endif
+#endif  /* SOCKET_DEBUG */
+      return 0;
+    }
+    else
+    {
+      totalBytes += (unsigned int)readBytes;
+
+      GETTIME (timeout) ;
+
+      if( totalBytes < reqLen )
+      {
+        if (attempts++)   /* try to get data by two consecutive accesses
+                             then sleep (but this should not be necessary) */
+        {
+#ifdef OLD_FRAME
+          Sleep (1) ;
+#else
+          os_SuspendTask ( 0, 1 );
+#endif
+        }
+      }
+      else
+      {
+        return totalBytes;
+      }
+    }
+  } while (timeout < stop_timeout);
+
+  return 0;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function    : socket_Read
++------------------------------------------------------------------------------
+| Description : This function is used to read data from the USART driver. The
+|               data is copied into the buffer to which out_BufferPtr points.
+|               The parameter *thr_BufferSizePtr contains the size of the
+|               buffer in characters.
+|               In the case of a successful completion, the driver's buffer
+|               is cleared. The driver keeps the data available when calling
+|               the function drv_Look().
+|               If the driver is not configured, the function returns
+|               DRV_NOTCONFIGURED.
+|
+|               NOTE: When calling the function with a buffer size of 0, the
+|                     function will return DRV_OK. The size of the buffer
+|                     needed to store the available data is stored in the
+|                     parameter *thr_BufferSizePtr. In this case, the
+|                     out_BufferPtr can be set to NULL.
+|
+|
+| Parameters  : out_BufferPtr         - This parameter points to the buffer
+|                                       wherein the data is to be copied
+|               thr_BufferSizePtr     - On call: number of characters to
+|                                       read. If the function returns DRV_OK,
+|                                       it contains the number of characters
+|                                       read. If the function returns
+|                                       DRV_INPROCESS, it contains 0.
+|
+| Return      : DRV_OK             - Function successful
+|               DRV_INPROCESS      - The driver is currently reading data.
+|                                    The data is incomplete.
+|               DRV_NOTCONFIGURED  - The driver is not yet configured
+|               SOCKET_NOCONNECT   - Connection not available
+|
++------------------------------------------------------------------------------
+*/
+USHORT socket_Read (void* out_BufferPtr, ULONG*  thr_BufferSizePtr)
+{
+#ifdef _VXWORKS_
+  SIZETYPE           pending_data_size = 0;
+#else
+  ULONG              pending_data_size = 0;
+#endif
+  ULONG              bytesToRead, bytesReq;
+  int                rc;
+  static USHORT      packet_size;
+  union
+  {
+    USHORT s;
+    UBYTE  b[2];
+  } conv;
+#ifdef SOCKET_DEBUG
+  static ULONG BytesRead = 0;
+#endif
+#ifdef SOCK_TRACE
+  static ULONG start;
+  static ULONG lasttime = 0;
+#endif
+
+  bytesReq = *thr_BufferSizePtr;
+  *thr_BufferSizePtr = 0;      /* no bytes returned yet */
+  while ( (rc = (GETREADSIZE( L_ClientData.Socket, &pending_data_size ))) == 0 &&
+          pending_data_size > 0 )
+  {
+    switch (sock_state)
+    {
+      case SST_PL0:
+#ifdef SOCK_TRACE
+        GETTIME (start) ;
+#endif
+        packet_size = 0;
+        if (pending_data_size >= 2)
+        {
+          bytesToRead = 2;
+          sock_state = SST_DATA0;
+        }
+        else
+        {
+          bytesToRead = 1;
+          sock_state = SST_PL1;
+        }
+        if ( !(L_DCB.config & TI_MODE) )
+        {
+          if (socket_Read_with_Timeout(&packet_size, bytesToRead) != bytesToRead)
+          {
+            sock_state = SST_PL0;
+            return SOCKET_NOCONNECT;
+          }
+        }
+        break;
+      case SST_PL1:
+        if (socket_Read_with_Timeout(((char*)&packet_size)+1, 1) != 1)
+        {
+          sock_state = SST_PL0;
+          return SOCKET_NOCONNECT;
+        }
+        sock_state = SST_DATA0;
+        break;
+      case SST_DATA0:
+        if ( !(L_DCB.config & TI_MODE) && isLittleEndian )
+        {
+          conv.b[0] = *(((UBYTE*)&packet_size)+1); /* LSB */
+          conv.b[1] = *  (UBYTE*)&packet_size;     /* MSB */
+          packet_size = conv.s;
+        }  
+        /*lint -fallthrough*/
+      case SST_DATAx:
+        /* now read the packet payload or a part of it */
+        if ( L_DCB.config & TI_MODE )
+        {
+          bytesToRead = (pending_data_size < bytesReq) ? pending_data_size : bytesReq;
+        }
+        else
+        {
+          bytesToRead = (packet_size < bytesReq) ? packet_size : bytesReq;
+          if (pending_data_size < bytesToRead)
+            bytesToRead = pending_data_size;
+        }
+        if( (*thr_BufferSizePtr =
+              socket_Read_with_Timeout( ((char *)out_BufferPtr), bytesToRead )) !=
+              bytesToRead )
+        {
+          *thr_BufferSizePtr = 0;
+          if ( !(L_DCB.config & TI_MODE) )
+            sock_state = SST_PL0;
+          return SOCKET_NOCONNECT;
+        }
+#ifdef SOCK_TRACE
+        if (fh_sock != -1 && sock_state == SST_DATA0 && bytesToRead >= 13)
+        {
+          char split[10+1];
+          char sstart[20], sstop[20];
+          static ULONG c_received = 0;
+          ULONG len = packet_size;
+          ULONG stop = GetTickCount();
+
+          if (((char*)out_BufferPtr)[13] == 'T')
+          {
+            memcpy(split, ((char*)out_BufferPtr)+9, 7);
+            split[7] = '\0';
+          }
+          else
+          {
+            memcpy(split, ((char*)out_BufferPtr)+9, 4);
+            split[4] = '\0';
+          }
+          if (start != lasttime)
+          {
+            if (lasttime - start > 11)
+              sprintf(sstart, "->%d %03d:%03d\n", c_received, (start/1000) % 1000, start % 1000);
+            else
+              sprintf(sstart, "%03d:%03d\n", (start/1000) % 1000, start % 1000);
+            c_received = 0;
+          }
+          c_received += packet_size + 2;
+          if (start != stop)
+          {
+            sprintf(sstop, "->%d %03d:%03d\n", c_received, (stop/1000) % 1000, stop % 1000);
+            c_received = 0;
+          }
+          sprintf(stbuf, "%s%d %s\n%s",
+                       (start != lasttime) ? sstart : "",
+                       packet_size + 2, split,
+                       (start != stop) ? sstop : "");
+          write (fh_sock, stbuf, strlen(stbuf));
+          lasttime = stop;
+        }
+#endif
+        if ( !(L_DCB.config & TI_MODE) )
+        {
+          if (*thr_BufferSizePtr == packet_size)
+            sock_state = SST_PL0;
+          else
+          {
+            packet_size -= (USHORT)*thr_BufferSizePtr;
+            sock_state = SST_DATAx;
+          }
+        }
+        return DRV_OK;
+    /*lint -e527 suppress Warning -- Unreachable */
+        break;
+    /*lint +e527 */
+    }  /* switch */
+  } /* while */
+  if (rc)
+  {
+    sock_state = SST_PL0;
+    return SOCKET_NOCONNECT;
+  }
+#ifdef SOCKET_DEBUG
+  {
+    static char Buffer[2000];
+    memcpy (Buffer+BytesRead,out_BufferPtr,*thr_BufferSizePtr);
+    BytesRead += *thr_BufferSizePtr;
+    if ( (Buffer[0] == 'P') )
+    {
+      OS_TIME time;
+      char c = Buffer[21];
+      fp = fopen(logfile, "at");
+      Buffer[21] = 0;
+      os_GetTime ( 0, &time );
+      fprintf (fp, "P%ld IN:  %s\n", time/10, &Buffer[9] );
+      Buffer[21] = c;
+      fclose(fp);
+    }
+  }
+
+#endif
+  return DRV_OK ;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function    : socket_Write
++------------------------------------------------------------------------------
+| Description : This function is used to write data to the driver. The
+|               parameter *thr_BufferSizePtr contains the number of
+|               characters to write. In the case of a successful completion,
+|               the function returns DRV_OK.
+|               If the data cannot be written because the storage capacity of
+|               the driver has been exhausted, the function returns
+|               DRV_BUFFER_FULL and the maximum number of characters that can
+|               be written in *thr_BufferSizePtr.
+|               If the driver is currently busy writing data and therefore
+|               cannot accept further data to be written, it returns
+|               DRV_INPROCESS and sets the parameter *thr_BufferSizePtr to 0.
+|               If the driver is not configured, the function returns
+|               DRV_ NOTCONFIGURED.
+|
+|               NOTE:  When calling the function with a buffer size of 0, the
+|                     function will return the number of characters that can be
+|                     written in the parameter *thr_BufferSizePtr. In this
+|                     case, the in_BufferPtr can be set to NULL.
+|
+| Parameters  : in_BufferPtr          - This parameter points to the buffer
+|                                       that is passed to the driver for
+|                                       further processing
+|               thr_BufferSizePtr     - On call: number of characters to
+|                                       write. If the function returns
+|                                       DRV_BUFFER_FULL, it contains the
+|                                       maximum number of characters that can
+|                                       be written. If the function returns
+|                                       DRV_OK, it contains the number of
+|                                       characters written. If the function
+|                                       returns DRV_INPROCESS, it contains 0.
+|
+|
+| Return      : DRV_OK            - Function successful
+|               DRV_BUFFER_FULL   - Not enough space
+|               DRV_INPROCESS     - Driver is busy writing data
+|               DRV_NOTCONFIGURED - The driver is not yet configured
+|               SOCKET_NOCONNECT  - Connection not available
+|
++------------------------------------------------------------------------------
+*/
+/*lint -esym(613,auxb) suppress warning possibly use off NULL pointer auxb */
+/*lint -esym(644,auxb) suppress warning possibly not initialized */
+/*lint -e668           suppress warning possibly passing NULL pointer to memcpy */
+USHORT socket_Write (void*  in_BufferPtr, ULONG*  thr_BufferSizePtr)
+{
+  UBYTE    rc = DRV_OK;
+  int   max_len, rest;
+  char *   auxb;
+  ULONG buffer_size;
+  
+  buffer_size = *thr_BufferSizePtr & ~PRIM_FLAG_MASK;
+
+#ifndef _PSOS_
+#ifdef SOCKET_DEBUG
+  UBYTE Prim = 0;
+  {
+    char *ptr = in_BufferPtr;
+    if ( *ptr == 'P' )
+    {
+      OS_TIME time;
+      char c = ptr[21];
+      fp = fopen(logfile, "at");
+      ptr[21] = 0;
+      os_GetTime ( 0, &time );
+      fprintf (fp, "P%ld OUT: %s\n", time/10, &ptr[9] );
+      ptr[21] = c;
+      fclose(fp);
+      Prim = 1;
+    }
+  }
+#endif  /* SOCKET_DEBUG */
+#else /* _PSOS */
+  if( !tst_socket_initialized )
+  {
+    if (tst_socket_in_TxLen > 0)
+    {
+      int nodelay = TRUE;
+      if (setsockopt(tst_socket, SOL_SOCKET, SO_SNDBUF,
+                     (char*)&tst_socket_in_TxLen, sizeof(tst_socket_in_TxLen)))
+        return DRV_INITFAILURE;
+      if (setsockopt(tst_socket, IPPROTO_TCP, TCP_NODELAY,
+                   (char*)&nodelay, sizeof(nodelay)))
+        return DRV_INITFAILURE;
+    }
+    tst_socket_initialized = 1;
+  }
+#endif /* _PSOS_ */
+
+  if ( L_DCB.config & TI_MODE )
+  {
+    /* add TI-MUX header */
+    auxb=(char*)malloc(buffer_size+2);
+    memcpy((void*)(auxb+2),in_BufferPtr,buffer_size);
+    auxb[0]=19; /* assigned to L23 */
+    auxb[1]=(char)buffer_size;
+    in_BufferPtr=auxb;
+    buffer_size+=2;
+  }
+
+  max_len = (L_DCB.tx_buffer_size < WRBUF_LEN) ? L_DCB.tx_buffer_size : WRBUF_LEN;
+  if (max_len < (int)buffer_size)
+  {
+#ifndef _PSOS_
+#ifdef SOCKET_DEBUG
+    char buffer[200];
+    char *ptr = in_BufferPtr;
+    char c = ptr[21];
+    fp = fopen(bufferfullfile, "at");
+    if ( *ptr == 'P' )
+      ptr[21] = 0;
+    else
+      ptr[buffer_size] = 0;
+    strcpy (buffer, "errno:" );
+    sprintf (&buffer[6], "%8d", WSAGetLastError() );
+    buffer[14] = ' ';
+    memcpy (&buffer[15], ptr, (buffer_size)+1);
+    fprintf (fp, "%s\n", buffer );
+    ptr[21] = c;
+    fclose(fp);
+#endif  /* SOCKET_DEBUG */
+#endif  /* _PSOS_ */
+    if ( L_DCB.config & TI_MODE )
+      free(auxb);
+    *thr_BufferSizePtr = (unsigned int)max_len |
+                                      (*thr_BufferSizePtr & PRIM_FLAG_MASK) ;
+    return DRV_BUFFER_FULL ;
+  }
+
+  rest = MAX_ETH_LEN - (wrbuf_pos - wrbuf);
+  if (buffer_size + 2 >= (unsigned int)rest)    /* more than maximum ethernet packet size needed ?*/
+  {
+  /*---------------------------------
+    send the buffer
+    ---------------------------------*/
+    rc = socket_WriteToOS(wrbuf, (USHORT)(wrbuf_pos - wrbuf));
+    wrbuf_pos = wrbuf;
+
+    if (rc != DRV_OK)
+    {
+      if ( L_DCB.config & TI_MODE )
+        free(auxb);
+      *thr_BufferSizePtr = (*thr_BufferSizePtr & PRIM_FLAG_MASK) ;
+      return rc;
+    }
+  }
+
+  if ( !(L_DCB.config & TI_MODE) )
+  {
+    /*------------------------------------------------
+      put the size of the data into buffer (MSB first)
+      ------------------------------------------------*/
+    if (isLittleEndian)
+    {
+      *wrbuf_pos     = *(((UBYTE*)&buffer_size)+1); /* MSB */
+      *(wrbuf_pos+1) = *  (UBYTE*)&buffer_size;     /* LSB */
+    }
+    else
+      *((USHORT*)wrbuf_pos) = (USHORT)buffer_size;
+    wrbuf_pos += 2;
+  }
+  /*---------------------------------
+    put the data itself into buffer
+    ---------------------------------*/
+  memcpy(wrbuf_pos, in_BufferPtr, (size_t)buffer_size);
+  wrbuf_pos += buffer_size;
+
+  if (socket_flush)
+  {
+    /*---------------------------------
+      send the buffer
+      ---------------------------------*/
+    rc = socket_WriteToOS(wrbuf, (USHORT)(wrbuf_pos - wrbuf));
+    wrbuf_pos = wrbuf;
+    socket_flush = 0;
+
+    if (rc != DRV_OK)
+    {
+      *thr_BufferSizePtr = (*thr_BufferSizePtr & PRIM_FLAG_MASK) ;
+    }
+  }
+
+  if ( L_DCB.config & TI_MODE )
+  {
+    free(auxb);
+  }
+  return rc ;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function    : socket_Flush
++------------------------------------------------------------------------------
+| Description : This function flushes the socket write buffer where data
+|               is stored until a complete packet can be sent or the
+|               transmission is forced by an external setting of the
+|               socket_flush flag. 
+|
+| Parameters  : ---
+|
+| Return      : DRV_OK                  - Function completed successfully
+|
++------------------------------------------------------------------------------
+*/
+USHORT socket_Flush ( void )
+{
+ULONG len = 0;
+
+  socket_flush = 1;
+  return ( socket_Write(NULL, &len) );
+}
+
+/*
++------------------------------------------------------------------------------
+| Function    : socket_SetSignal
++------------------------------------------------------------------------------
+| Description : This function is used to define a single or multiple signals
+|               that is/are indicated to the process when the event identified
+|               in the signal information data type as SignalType occurs. The
+|               USART uses only the standard signals defined in [C_8415.0026].
+|               To remove a signal, call the function socket_ResetSignal().
+|               If one of the parameters of the signal information data is
+|               invalid, the function returns DRV_INVALID_PARAMS.
+|               If no signal call-back function has been defined at the time
+|               of initialization, the driver returns DRV_SIGFCT_NOTAVAILABLE.
+|
+| Parameters  : in_SignalIDPtr        - Pointer to the signal information
+|                                       data
+|
+| Return      : DRV_OK                  - Function completed successfully
+|               DRV_INVALID_PARAMS      - One or more parameters are out of
+|                                         range or invalid
+|               DRV_SIGFCT_NOTAVAILABLE - Event signaling functionality is
+|                                         not available
+|
++------------------------------------------------------------------------------
+*/
+USHORT socket_SetSignal (USHORT SignalType)
+{
+  if (L_ClientData.Callback == NULL)
+    return DRV_SIGFCT_NOTAVAILABLE ;
+
+  if (SignalType & ALLOWED_SOCKET_SIGNALS)
+    L_ClientData.EnabledSignals |= SignalType;
+  else
+    return DRV_INVALID_PARAMS ;
+  return DRV_OK ;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function    : socket_ResetSignal
++------------------------------------------------------------------------------
+| Description : This function is used to remove previously set single or
+|               multiple signals. The signals that are removed are identified
+|               by the Signal Information Data element called SignalType. All
+|               other elements of the Signal Information Data must be
+|               identical to the signal(s) that are to be removed (process
+|               handle and signal value). If the SignalID provided cannot be
+|               located, the function returns DRV_INVALID_PARAMS.
+|               If no signal call-back function has been defined at the time
+|               of initialization, the driver returns DRV_SIGFCT_NOTAVAILABLE.
+|
+| Parameters  : in_SignalIDPtr        - Pointer to the signal information
+|                                       data
+|
+| Return      : DRV_OK                    - Function completed successfully
+|               DRV_INVALID_PARAMS        - One or more parameters are out of
+|                                           range or invalid
+|               DRV_SIGFCT_NOTAVAILABLE   - Event signaling functionality is
+|                                           not available
+|
++------------------------------------------------------------------------------
+*/
+USHORT socket_ResetSignal (USHORT SignalType)
+{
+  if (L_ClientData.Callback == NULL)
+    return DRV_SIGFCT_NOTAVAILABLE ;
+
+  if (SignalType & ALLOWED_SOCKET_SIGNALS)
+    L_ClientData.EnabledSignals &= ~SignalType;
+  else
+    return DRV_INVALID_PARAMS ;
+
+  return DRV_OK ;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function    : socket_SetConfig
++------------------------------------------------------------------------------
+| Description : This function is used to configure the driver (port,
+|               transmission rate, flow control, etc). The driver can be
+|               configured at any one time before a connection is opened. The
+|               parameters that can be configured are included in the USART's
+|               device control block socket_DCB_Type. For detailed information
+|               about the contents of the device control block, refer to
+|               Chapter 2.1.1. If any value of the configuration is out of
+|               range or invalid in combination with any other value of the
+|               configuration, the function returns DRV_INVALID_PARAMS.
+|               Call the socket_GetConfig() function to retrieve the driver's
+|               configuration.
+|               The driver needs to be configured after initialization. Only
+|               the following functions can be called while the driver is not
+|               configured: socket_Clear, socket_SetSignal and socket_GetSignal.
+|               All other functions return DRV_NOTCONFIGURED.
+|
+| Parameters  : in_DCBPtr             - Pointer to the driver control block
+|
+| Return      : DRV_OK                    - Function completed successfully
+|               DRV_INVALID_PARAMS        - One or more parameters are out of
+|                                           range or invalid
+|
++------------------------------------------------------------------------------
+*/
+USHORT socket_SetConfig (char* in_DCBPtr)
+{
+char token [SOCKET_MAX_LEN_HOSTNAME+1];
+USHORT port;
+unsigned int len;
+
+  if ( (len = GetNextToken (in_DCBPtr, token, " #")) == 0)
+  {
+    return DRV_INVALID_PARAMS;
+  }
+  else
+  {
+    in_DCBPtr += (len+1);
+  }
+
+  port = (USHORT)atoi(token);
+
+  if ( (len = GetNextToken (in_DCBPtr, token, " #")) == 0) 
+  {
+    return DRV_INVALID_PARAMS;
+  }
+  else
+  {
+    in_DCBPtr += (len+1);
+  }
+
+  if ( !strcmp ( DRV_TI_MODE, token ) )
+  {
+    L_DCB.config = TI_MODE;
+    sock_state = SST_DATAx;
+  }
+  else if ( !strcmp ( DRV_DEFAULT, token ) )
+  {
+    L_DCB.config = 0;
+    sock_state = SST_PL0;
+  }
+  else
+    return DRV_INVALID_PARAMS;
+
+  if ( (len = GetNextToken (in_DCBPtr, token, " #")) == 0 ) 
+  {
+#ifdef _TOOLS_
+    gethostname (token,SOCKET_MAX_LEN_HOSTNAME);
+#endif /* _TOOLS_ */
+  }
+
+  if (L_ThreadActive)
+  {
+    /* check if host is already used */
+    if (strcmp(L_DCB.hostname, token)==0 && L_DCB.port==port) 
+    {
+#ifdef _TOOLS_
+      printf("SOCKET: keeping connection to host %s on port %u\n",L_DCB.hostname,L_DCB.port); 
+#endif
+      return DRV_OK;
+    }
+
+    socket_Close();
+  }
+  
+  L_DCB.port=port;
+  strcpy ( L_DCB.hostname, token);
+  
+  if (socket_Open () != DRV_OK)
+  {
+    return DRV_INVALID_PARAMS ;
+  }
+
+  return DRV_OK ;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function    : socket_GetConfig
++------------------------------------------------------------------------------
+| Description : This function is used to retrieve the configuration of the
+|               driver. The configuration is returned in the driver control
+|               block to which the pointer provided out_DCBPtr points. For
+|               detailed information about the contents of the device control
+|               block, refer to Chapter 2.1.1. The configuration can be
+|               requested at any one time.
+|               If the driver is not configured, the function returns
+|               DRV_ NOTCONFIGURED.
+|
+| Parameters  : out_DCBPtr                - Pointer to the driver control block
+|
+| Return      : DRV_OK                    - Function completed successfully
+|               DRV_INVALID_PARAMS        - One or more parameters are out of
+|                                           range or invalid
+|
++------------------------------------------------------------------------------
+*/
+USHORT socket_GetConfig (socket_DCB_Type*  out_DCBPtr)
+{
+  if (out_DCBPtr == NULL)
+    return DRV_INVALID_PARAMS ;
+
+  memcpy (out_DCBPtr, &L_DCB, sizeof (L_DCB)) ;
+  return DRV_OK ;
+}
+
+/*
++------------------------------------------------------------------------------
+| Function    : socket_Init
++------------------------------------------------------------------------------
+| Description : The function initializes the internal data of the driver.
+|               The function returns DRV_INITIALIZED if the driver has
+|               already been initialized and is ready to be used or is
+|               already in use. In the case of an initialization failure,
+|               i.e. the driver cannot be used, the function returns
+|               DRV_INITFAILURE.
+|
+| Parameters  : in_SignalCBPtr    - This parameter points to the function that
+|                                   is called at the time an event that is to
+|                                   be signaled occurs. This value can be set
+|                                   to NULL if event signaling should not be
+|                                   possible.
+|
+| Return      : DRV_OK            - Initialization successful
+|               DRV_INITIALIZED   - Driver already initialized
+|               DRV_INITFAILURE   - Initialization failed
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL USHORT socket_Init ( USHORT DrvHandle, T_DRV_CB_FUNC CallbackFunc, T_DRV_EXPORT const **DrvInfo )
+{
+static const T_DRV_EXPORT Socket_Info =
+{
+  "SOCKET",
+  0,
+  {
+#ifdef _TOOLS_
+    socket_Init,
+#endif
+    socket_Exit,
+    socket_Read,
+    socket_Write,
+    NULL,
+    NULL,
+    socket_Flush,
+    socket_SetSignal,
+    socket_ResetSignal,
+    socket_SetConfig,
+    NULL,
+    NULL,
+  }
+};
+union
+{
+  USHORT s;
+  UBYTE b[2];
+} test;
+
+#ifndef _PSOS_
+#if defined (_VXWORKS_) || defined (_LINUX_) || defined (_SOLARIS_)
+/* ToDo: vxWorks-libs initiieren
+  sockLib
+  inetLib
+*/
+#else /* _VXWORKS_ */
+  WSADATA WSAData;
+  if (WSAStartup(MAKEWORD(1,1), &WSAData))
+    return DRV_INITFAILURE;
+#endif /* _VXWORKS_ */
+#endif
+
+  test.s = 1;
+  isLittleEndian = (test.b[0] == 1);
+
+  L_ThreadActive = FALSE ;
+  L_DCB.config = 0;
+  L_DCB.port = 6392;
+  L_DCB.tx_buffer_size = TX_BUFFER_SIZE;
+  L_DCB.rx_buffer_size = RX_BUFFER_SIZE ;
+  L_DCB.tx_timeout_msec = TX_TIMEOUT_MSEC;
+  L_DCB.rx_timeout_msec = RX_TIMEOUT_MSEC;
+  *L_DCB.hostname = 0 ;
+  L_ClientData.Connect = FALSE;
+  L_ClientData.SocketHandle = DrvHandle;
+  L_ClientData.Socket = INVALID_SOCKET ;
+  L_ClientData.Listener = INVALID_SOCKET ;
+#ifdef _PSOS_
+  tst_socket = INVALID_SOCKET ;
+  tst_socket_initialized = 0;
+  tst_socket_in_TxLen = 0;
+#endif
+
+  L_ClientData.Callback   = CallbackFunc ;
+  L_ClientData.EnabledSignals = ALLOWED_SOCKET_SIGNALS ;
+  *DrvInfo = &Socket_Info;
+#ifdef SOCKET_DEBUG
+  fp = fopen(logfile,"wt");
+  fclose(fp);
+  fp = fopen(inprocessfile,"wt");
+  fclose(fp);
+  fp = fopen(bufferfullfile,"wt");
+  fclose(fp);
+  fp = fopen(noconnectfile1,"wt");
+  fclose(fp);
+  fp = fopen(noconnectfile2,"wt");
+  fclose(fp);
+  fp = fopen(noconnectfile3,"wt");
+  fclose(fp);
+  fp = fopen(readerrorfile,"wt");
+  fclose(fp);
+#endif /* SOCKET_DEBUG */
+  return DRV_OK ;
+}
+
+/*==== END OF FILE ==========================================================*/
+