This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Need insight for the Ethernet ability for the TMS320C6748

Other Parts Discussed in Thread: TMS320C6748

Hello,

I need some assistance for the Ethernet implementation on my custom board with DSP TMS320C6748 processor.

I am using ccs6 and latest NDK and XDCtools along with bios6_33. I have rebuild the NDK core with rebuilding instructions given on the webpage. Moreover, I have latest version of the NSP also and PHY is LAN8710AI same as the LCDK6748.

  From here, what should i read to get a headstart on the firmware development?

Please guide me if you have implemented anything same as this.

Thanks in advance.

  • Your tools are slightly ahead of me (I use CCSV5.5), so what I have to say might not be completely correct. Please see my posts below. It is a lot of information to digest, but should get you pointed in the right direction. The TI documentation for the NDK is way out of date.

    e2e.ti.com/.../393466
    e2e.ti.com/.../433599
    e2e.ti.com/.../437285

    Finally, since you are using a custom board, watch out if your input crystal isn't 24MHz. See below

    e2e.ti.com/.../261263

    - Dean
  • Thanks Dean...that was some hopes to dawn into the dark and never ending literature of the TI. I would come back to you after i follow all these links you gave.
    By the way, i have followed the LCDK6748 kit to make my board and i hv used ll those 50MHZ crystals to run the DSP.
    However, could you please tell me where you would start with client.c (which is always referanced in all the wiki/blogs). In my NSP client.c its hardly few lines and i am just selecting the .cfg where i can check mark.
    And i saw that you have made many valid arguments t them but how would you make your DSP communicative in the real world? i.e. do we have steps that says that first configure emac than mdio than ip and udp and so on..!

    I am bit demanding and i apologize for this though this is all because ti's guidelines are so obsolete and poor!
  • Axay,

    I may no longer be a good source for NDK questions.  The TI supplied NSP was so poorly written, and inefficient, I've completely re-written it.  Uses less memory, executes a lot faster, etc.  The cost of this re-write is it is difficult to go back to the "old" TI NSP.  You will need to understand Berkeley Socket Programming in order to use the NDK correctly.  See the following link for a good overview: 

  • Thanks Dean!
    This is quite useful!

    I just want to have your perspective about buying the LCDK6748 and trying the example. would it be helpful?
  • We have never used the LCDK6748.  I find the process of getting something working on a DEV board, and then porting to a custom board, more of a headache than useful.  Below is a file that implements a TCP listen socket.  Good luck.

    /********************************************************************************************************************************/
    /********************************************************************************************************************************/
    /*                                                 ETHERNET_SOCKET_LINE01TO08.C                                                 */
    /*                                COPYRIGHT NOTICE: (c) Ultratec, Inc.  2015  ALL RIGHTS RESERVED                               */
    /********************************************************************************************************************************/
    /*                                                                                                                              */
    /*                Model:   Agent Port Card  (Board Revision 000-030551)                                                         */
    /* SYSBIOS Requirements:   0 HWI vector, 0 SWI vectors, 0 CLK, 1 TASK                                                           */
    /*                                                                                                                              */
    /* This file has functions for the TCP Socket that controls Phone lines 1 to 8.                                                 */
    /*                                                                                                                              */
    /********************************************************************************************************************************/
    #include <ti/sysbios/BIOS.h>              /* SYSBIOS file.  Must be 1st when using SYSBIOS routines or objects. */
    #include <xdc/cfg/global.h>               /* SYSBIOS file.  Defines all static SYSBIOS objects from the .cfg file. */
    #include <ti/sysbios/knl/Task.h>
    #include <netmain.h>                      /* NDK master include file. */
    #include <string.h>                       /* C system file.  memset(), strcpy(), strcmp(), etc. */
    #include "TI_C6748.h"
    #include "PhoneLines.h"
    #include "StatusLEDs.h"
    #include "AgentPortCardV2.h"
    #include "Ethernet_NDK_Hooks.h"
    #include "Ethernet_Socket_TCP.h"
    #include "Ethernet_Socket_Broadcast.h"
    #include "Ethernet_Socket_Line01to08.h"
    
    
    /*************************/
    /* Global File Variables */
    /*************************/
    /* None */
    
    /************************/
    /* Local File Variables */
    /************************/
    /* !!! Important !!!  None of these variables have a defined initial value.  Please use ResetSocket01to08() to provide the initial
       value.  Doing it this way means there is one, and only one, place for the initial values.  There is no chance of the 1st time
       through the socket code behaving differently than the 2nd time through. */
    static SOCKET ListenSocket1;                       /* Master socket that listens for connections. */
    static SOCKET ConnectSocket1;                      /* Socket created once a connection is accepted. */
    static TCPSocketMachine Line01to08_Eth_State;      /* Socket control state machine. */
    static U8 TCP01to08RXData[256];
    static U8 TCP01to08TXData[256];
    static U32 TCP01to08TXIndex;
    
    /*****************************/
    /* Local Function Prototypes */
    /*****************************/
    static void ResetSocket01to08(BOOL IsFullReset);
    static void CreateSocket01to08(void);
    static void ConfigSocketOptions01to08(void);
    static void BindSocket01to08(void);
    static void ListenSocket01to08(void);
    static BOOL ReceiveData01to08(void);
    static BOOL SendData01to08(void);
    static void ProcessRXedData01to08(U32 RxSize);
    static BOOL SingleByteCommand01to08(U8 Command);
    static void MultiByteCommand01to08(U8 Command, U8 RxData);
    static void CloseConnectSocket01to08();
    static void Check01to08Ringing(void);
    
    
    
    
    /********************************************************************************************************************************/
    /********************************************************************************************************************************/
    /****************************************************  SYSBIOS FUNCTIONS  *******************************************************/
    /********************************************************************************************************************************/
    /********************************************************************************************************************************/
    
    /*** TSK function *************************************** TSK function ***************************************** TSK function ***/
    /*******************************************   TSK PRIORITY LEVEL = OS_TASKPRINORM   ********************************************/
    /********************************************************************************************************************************/
    /*  void Line01to08Control(UArg NotUsed0, UArg NotUsed1)                                                                        */
    /*                                                                                                                              */
    /*  This task handles the master Listen socket and the Connection socket for Phone lines 1-8.  We only accept 1 connection at   */
    /*  a time.                                                                                                                     */
    /*                                                                                                                              */
    /*  Parameters:                                                                                                                 */
    /*      - NotUsed0:  This value is passed to us via the TASK Module, arg0.  We don't have a need for it.                        */
    /*      - NotUsed1:  This value is passed to us via the TASK Module, arg1.  We don't have a need for it.                        */
    /*                                                                                                                              */
    /*  Returns:  never (this TASK loops forever and never returns)                                                                 */
    /*                                                                                                                              */
    /*  Notes:                                                                                                                      */
    /*    1. The NDK assumes we are using TI's BIOS.  BIOS task priority:  OS_TASKPRINORM (configurable option NDK->Scheduling)     */
    /*    2. This task starts out in the INACTIVE state.  It is only released to run from the NDK hook:  UnleashEthTasks().         */
    /********************************************************************************************************************************/
    void Line01to08Control(UArg NotUsed0, UArg NotUsed1)
    {
       struct sockaddr_in ListenSA1;
       S32 ListenSA1SizeinBytes = sizeof(ListenSA1);
    
       Line01to08_Eth_State = TCP_SOCKET_ETHERNET_CABLE_CHECK;
       for(;;)                       /* Infinite loop.  This task never exits. */
       {
          switch(Line01to08_Eth_State)
          {
    /****************/
    /* CABLE CHECK  */
    /****************/
             case TCP_SOCKET_ETHERNET_CABLE_CHECK:
                ResetSocket01to08(TRUE);                  /* Initialize all static variables and get the phone lines onhook. */
                while( EthernetCableCheck() == FALSE )
                {
                   Task_sleep(500);     /* Sleep 500mS and then check again. */
                }
                Line01to08_Eth_State = TCP_SOCKET_SETUP;
                break;
    
    /**************/
    /* SETUP      */
    /**************/
             case TCP_SOCKET_SETUP:
                /* Before we can use any socket functions, fdOpenSession() must be called.  This is a NDK requirement. */
                if( fdOpenSession((HANDLE)Task_self()) == 0 )
                {
                   NDKFatalError(NDK_LINE01TO08_SOCKET_FD_MEMORY_FAIL, 0);
                }
    
                CreateSocket01to08();
                ConfigSocketOptions01to08();
                BindSocket01to08();
                ListenSocket01to08();
                Line01to08_Eth_State = TCP_SOCKET_WAIT_FOR_CONNECTION;
                break;
    
    
    /************************/
    /* WAIT FOR CONNECTION  */
    /************************/
             case TCP_SOCKET_WAIT_FOR_CONNECTION:
                /* accept() will block if no connections are pending.  This allows other tasks to run. */
                memset(&ListenSA1, NULL, sizeof(ListenSA1));
                ConnectSocket1 = accept(ListenSocket1, (PSA)&ListenSA1, &ListenSA1SizeinBytes);
                if( ConnectSocket1 == INVALID_SOCKET )
                {
                   NDKFatalError(NDK_LINE01TO08_SOCKET_ACCEPT_FAIL, fdError());
                }
                Line01to08_Eth_State = TCP_SOCKET_CONNECTED;
                break;
    
    
    /**************/
    /* CONNECTED  */
    /**************/
             case TCP_SOCKET_CONNECTED:
                while( (Line01to08_Eth_State == TCP_SOCKET_CONNECTED) && (EthernetCableCheck() == TRUE) )
                {
                   /* Zero out the RX and TX buffers prior to checking the NDK for more data. */
                   TCP01to08TXIndex = 0;
                   memset(TCP01to08TXData, NULL, sizeof(TCP01to08TXData));
                   memset(TCP01to08RXData, NULL, sizeof(TCP01to08RXData));
    
                   /* ReceiveData01to08() will block if no data is available.  This allows other tasks to run. */
                   if( ReceiveData01to08() == TRUE )
                   {
                      Check01to08Ringing();
    
                      /* As a result of what we just received, or after the ring check, do we now have something to TX? */
                      if( TCP01to08TXIndex != 0 )
                      {
                         if( SendData01to08() == FALSE )
                         {
                            Line01to08_Eth_State = TCP_SOCKET_CLOSE;     /* Something wrong.  Most likely far end dropped connection. */
                         }
                      }
                   }
                   else
                   {
                      Line01to08_Eth_State = TCP_SOCKET_CLOSE;     /* That's all folks, far end dropped the connection. */
                   }
                }
                Line01to08_Eth_State = TCP_SOCKET_CLOSE;           /* CYA in case the Ethernet cable check fails. */
                break;
    
    
    /**************/
    /* CLOSE      */
    /**************/
             case TCP_SOCKET_CLOSE:
                CloseConnectSocket01to08();      /* Only close the connected socket.  Listen socket is still alive. */
    
                if( EthernetCableCheck() == FALSE )
                {
                   /* Kill the Listen socket and free the memory from the NDK.  We are going back to the beginning. */
                   fdClose(ListenSocket1);
                   fdCloseSession((HANDLE)Task_self());
                   Line01to08_Eth_State = TCP_SOCKET_ETHERNET_CABLE_CHECK;
                }
                else
                {
                   ResetSocket01to08(FALSE);                    /* Initialize all static variables and get the phone lines onhook. */
                   SkipOneUDPBroadcast(Line01_to_Line08);       /* Kurt wants to skip one broadcast after a socket close. */
                   Line01to08_Eth_State = TCP_SOCKET_WAIT_FOR_CONNECTION;
                }
                break;
    
    
    /**************/
    /* WTF        */
    /**************/
             default:
                /* If we ever get here, things are really F'ed up. */
                NDKFatalError(NDK_LINE01TO08_SOCKET_UNKNOWN_STATE, Line01to08_Eth_State);
                break;
          }
       }
    }
    
    
    
    
    /********************************************************************************************************************************/
    /********************************************************************************************************************************/
    /****************************************************  PUBLIC API FUNCTIONS  ****************************************************/
    /********************************************************************************************************************************/
    /********************************************************************************************************************************/
    
    /********************************************************************************************************************************/
    /*  TCPSocketMachine SocketLine01to08Status(void)                                                                               */
    /*                                                                                                                              */
    /*  Return the state machine value for the task that controls phone lines 1-8.                                                  */
    /*                                                                                                                              */
    /*  Parameters:                                                                                                                 */
    /*      - none                                                                                                                  */
    /*                                                                                                                              */
    /*  Returns:  state machine value for Line 1-8 task                                                                             */
    /*                                                                                                                              */
    /*  Notes:  Public API function that can be called from anywhere.                                                               */
    /********************************************************************************************************************************/
    TCPSocketMachine SocketLine01to08Status(void)
    {
       return(Line01to08_Eth_State);
    }
    
    
    
    
    /********************************************************************************************************************************/
    /********************************************************************************************************************************/
    /****************************************************  STATIC FUNCTIONS  ********************************************************/
    /********************************************************************************************************************************/
    /********************************************************************************************************************************/
    
    /********************************************************************************************************************************/
    /*  static void ResetSocket01to08(BOOL IsFullReset)                                                                             */
    /*                                                                                                                              */
    /*  This function resets all the file static variables and makes sure phone lines 1 through 8 are onhook.                       */
    /*                                                                                                                              */
    /*  Parameters:                                                                                                                 */
    /*      - IsFullReset:  TRUE = All static variables get RESET,  FALSE = Some of the static variables get RESET.                 */
    /*                                                                                                                              */
    /*  Returns:  none                                                                                                              */
    /*                                                                                                                              */
    /*  Notes:  none                                                                                                                */
    /********************************************************************************************************************************/
    static void ResetSocket01to08(BOOL IsFullReset)
    {
       /* Static variables that deal with the Listen socket, or control of the socket, only get RESET if full is requested. */
       if( IsFullReset == TRUE )
       {
          ListenSocket1 = INVALID_SOCKET;
          Line01to08_Eth_State = TCP_SOCKET_ETHERNET_CABLE_CHECK;
       }
    
       /* Initialize the file static variables. */
       ConnectSocket1 = INVALID_SOCKET;
       memset(TCP01to08RXData, NULL, sizeof(TCP01to08RXData));
       memset(TCP01to08TXData, NULL, sizeof(TCP01to08TXData));
       TCP01to08TXIndex = 0;
    
       InitializePhoneLine01to08();
    }
    
    
    /********************************************************************************************************************************/
    /*  static void CreateSocket01to08(void)                                                                                        */
    /*                                                                                                                              */
    /*  Create the master Listener socket.                                                                                          */
    /*                                                                                                                              */
    /*  Parameters:                                                                                                                 */
    /*      - none                                                                                                                  */
    /*                                                                                                                              */
    /*  Returns:  none                                                                                                              */
    /*                                                                                                                              */
    /*  Notes:  none                                                                                                                */
    /********************************************************************************************************************************/
    static void CreateSocket01to08(void)
    {
       /* Create the pointer to this listening socket.  This socket needs to be Internet TCP/IP.  The first parameter
          declares Internet, the second parameter must be used when TCP is selected, and finally the last parameter
          selects TCP.  This only allocates the memory, and initializes the socket structure.  Nothing is connected yet. */
       ListenSocket1 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
       if( ListenSocket1 == INVALID_SOCKET )
       {
          NDKFatalError(NDK_LINE01TO08_SOCKET_CREATE_FAIL, fdError());
       }
    }
    
    
    /********************************************************************************************************************************/
    /*  static void ConfigSocketOptions01to08(void)                                                                                 */
    /*                                                                                                                              */
    /*  Configure the socket parameters for the Listener socket.  I believe these options also carry over to the Connected socket.  */
    /*                                                                                                                              */
    /*  Parameters:                                                                                                                 */
    /*      - none                                                                                                                  */
    /*                                                                                                                              */
    /*  Returns:  none                                                                                                              */
    /*                                                                                                                              */
    /*  Notes:  none                                                                                                                */
    /********************************************************************************************************************************/
    static void ConfigSocketOptions01to08(void)
    {
       S32 len = 0;
       struct timeval tv;
    
       /* If we ever have to restart from scratch (Ethernet cable unplugged / plugged in event), then there is a chance
          that we'll need this option set.  It is commonly used on server applications (which this is). */
       len = 1;
       if( setsockopt(ListenSocket1, SOL_SOCKET, SO_REUSEADDR, &len, sizeof(len)) < 0 )
       {
          NDKFatalError(NDK_LINE01TO08_SOCKET_OPTION_FAIL, fdError());
       }
    
       /* Turn on TCP keep alive.  If there is no TCP traffic for a while, this option will send "Are you there" packets
          and expect a response.  If there is no response, it will terminate the socket.  Basically a far end down detector. */
       len = 1;
       if( setsockopt(ListenSocket1, SOL_SOCKET, SO_KEEPALIVE, &len, sizeof(len)) < 0 )
       {
          NDKFatalError(NDK_LINE01TO08_SOCKET_OPTION_FAIL, fdError());
       }
    
       /* Make sure blocking is ON.  We need recv() to block in the case there is no data to be read. */
       len = 1;
       if( setsockopt(ListenSocket1, SOL_SOCKET, SO_BLOCKING, &len, sizeof(len)) < 0 )
       {
          NDKFatalError(NDK_LINE01TO08_SOCKET_OPTION_FAIL, fdError());
       }
    
       /* Set the receive timeout to 3 seconds.  In case of no RX data, we need to wake up to check ring detect. */
       tv.tv_sec = 3;
       tv.tv_usec = 0;
       if( setsockopt(ListenSocket1, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0 )
       {
          NDKFatalError(NDK_LINE01TO08_SOCKET_OPTION_FAIL, fdError());
       }
    
       /* Disable the Nagle algorithm.  Keeps things moving in real time. */
       len = 1;
       if( setsockopt(ListenSocket1, IPPROTO_TCP, TCP_NODELAY, &len, sizeof(len)) < 0 )
       {
          NDKFatalError(NDK_LINE01TO08_SOCKET_OPTION_FAIL, fdError());
       }
    
       /* Enable SACK.  Not sure what this is, but Eric wants it ON for our network. */
       len = 1;
       if( setsockopt(ListenSocket1, IPPROTO_TCP, TCP_SACKPERMITTED, &len, sizeof(len)) < 0 )
       {
          NDKFatalError(NDK_LINE01TO08_SOCKET_OPTION_FAIL, fdError());
       }
    }
    
    
    /********************************************************************************************************************************/
    /*  static void BindSocket01to08(void)                                                                                          */
    /*                                                                                                                              */
    /*  Bind the Listener socket to a port number and IP address.                                                                   */
    /*                                                                                                                              */
    /*  Parameters:                                                                                                                 */
    /*      - none                                                                                                                  */
    /*                                                                                                                              */
    /*  Returns:  none                                                                                                              */
    /*                                                                                                                              */
    /*  Notes:  none                                                                                                                */
    /********************************************************************************************************************************/
    static void BindSocket01to08(void)
    {
       struct sockaddr_in ListenSA1;
    
       /* Associate this socket to the address and port we want to listen on. */
       memset(&ListenSA1, NULL, sizeof(ListenSA1));
       ListenSA1.sin_family = AF_INET;
       ListenSA1.sin_addr.s_addr = htonl(INADDR_ANY);
       ListenSA1.sin_port = htons(LINE01TO08_PORT);
       if( bind(ListenSocket1, (PSA)&ListenSA1, sizeof(ListenSA1)) < 0 )
       {
          NDKFatalError(NDK_LINE01TO08_SOCKET_BIND_FAIL, fdError());
       }
    }
    
    
    /********************************************************************************************************************************/
    /*  static void ListenSocket01to08(void)                                                                                        */
    /*                                                                                                                              */
    /*  Let the Ethernet stack know we want this socket setup to listen (server socket).                                            */
    /*                                                                                                                              */
    /*  Parameters:                                                                                                                 */
    /*      - none                                                                                                                  */
    /*                                                                                                                              */
    /*  Returns:  none                                                                                                              */
    /*                                                                                                                              */
    /*  Notes:  none                                                                                                                */
    /********************************************************************************************************************************/
    static void ListenSocket01to08(void)
    {
       /* Tell this socket we will be listening.  Max incoming connections waiting in queue = 2. */
       if( listen(ListenSocket1, 2) < 0 )
       {
          NDKFatalError(NDK_LINE01TO08_SOCKET_LISTEN_FAIL, fdError());
       }
    }
    
    
    /********************************************************************************************************************************/
    /*  static BOOL ReceiveData01to08(void)                                                                                         */
    /*                                                                                                                              */
    /*  Receive and process data from the Connected socket.  If no data is ready, recv() will block to allow other tasks to run.    */
    /*                                                                                                                              */
    /*  Parameters:                                                                                                                 */
    /*      - none                                                                                                                  */
    /*                                                                                                                              */
    /*  Returns:  TRUE = data was received and processed,  FALSE = shut down the connection                                         */
    /*                                                                                                                              */
    /*  Notes:  none                                                                                                                */
    /********************************************************************************************************************************/
    static BOOL ReceiveData01to08(void)
    {
       S32 RxSize = 0;
       BOOL rc = FALSE;
       S32 RecvError = 0;
    
       RxSize = recv(ConnectSocket1, TCP01to08RXData, sizeof(TCP01to08RXData), 0);
       if( RxSize > 0 )
       {
          ProcessRXedData01to08(RxSize);
          rc = TRUE;
       }
       else if( RxSize == 0 )
       {
          rc = FALSE;          /* The far end connection has dropped the socket. */
       }
       else
       {
          RecvError = fdError();
          if( RecvError == EWOULDBLOCK )
          {
             rc = TRUE;        /* Reached the timeout.  Not fatal. */
          }
          else if( RecvError == ECONNRESET )
          {
             /* Far end connect did an "unfriendly" socket shutdown.  In the future we want to send a NOCMON alert, then close the
                socket WITHOUT changing the state of the phone lines.  Something will tell us when we can finally reset the phone
                lines and start broadcasting again.  Until the NOCMON socket gets setup, for now we'll just sleep for 30 minutes,
                then close the socket, reset the phone lines, and start broadcasting again.  30 minutes will give us a very good
                chance that all calls will finish and we won't drop any. */
             Task_sleep(1800000);     /* Sleep for 30 minutes to allow all active calls to finish. */
             rc = FALSE;
          }
          else
          {
             NDKFatalError(NDK_LINE01TO08_SOCKET_RECV_FAIL, RecvError);
          }
       }
    
       return(rc);
    }
    
    
    /********************************************************************************************************************************/
    /*  static BOOL SendData01to08(void)                                                                                            */
    /*                                                                                                                              */
    /*  Send data to the Connected socket.                                                                                          */
    /*                                                                                                                              */
    /*  Parameters:                                                                                                                 */
    /*      - none                                                                                                                  */
    /*                                                                                                                              */
    /*  Returns:  TRUE = data was sent, no errors,  FALSE = non fatal send() error, most likely far end dropped the connection.     */
    /*                                                                                                                              */
    /*  Notes:  none                                                                                                                */
    /********************************************************************************************************************************/
    static BOOL SendData01to08(void)
    {
       U32 TotalBytesSent = 0;
       U32 BytesRemaining = TCP01to08TXIndex;
       S32 BytesSentThisAttempt = 0;
       S32 SendError = 0;
       BOOL rc = TRUE;         /* Assume everything will be OK. */
    
       while( (TotalBytesSent < TCP01to08TXIndex) && (rc == TRUE) )
       {
          BytesSentThisAttempt = send(ConnectSocket1, &TCP01to08TXData[TotalBytesSent], BytesRemaining, 0);
          if( BytesSentThisAttempt < 0 )
          {
             /* Check out the error returned and see if it fatal or not.  Sometimes send() fails because the far end disconnected,
                and in those cases we don't want to do the fatal lockup. */
             SendError = fdError();
             if( (SendError == EBADF) || (SendError == EMSGSIZE) || (SendError == ENOBUFS) || (SendError == ENOTSOCK) )
             {
                NDKFatalError(NDK_LINE01TO08_SOCKET_SEND_FAIL, SendError);
             }
             else
             {
                rc = FALSE;          /* We have a send() error but it's not fatal, just exit. */
             }
          }
          else
          {
             TotalBytesSent = TotalBytesSent + BytesSentThisAttempt;
             BytesRemaining = BytesRemaining - BytesSentThisAttempt;
          }
       }
    
       /* Reset all the TX buffer variables for next time. */
       memset(TCP01to08TXData, NULL, sizeof(TCP01to08TXData));
       TCP01to08TXIndex = 0;
    
       return(rc);
    }
    
    
    /********************************************************************************************************************************/
    /*  static void ProcessRXedData01to08(U32 RxSize)                                                                               */
    /*                                                                                                                              */
    /*  This function parses the data received from the socket that is controlling phone lines 1 through 8.                         */
    /*                                                                                                                              */
    /*  Parameters:                                                                                                                 */
    /*      - RxSize: number of bytes received that we need to process                                                              */
    /*                                                                                                                              */
    /*  Returns:  none                                                                                                              */
    /*                                                                                                                              */
    /*  Notes:  none                                                                                                                */
    /********************************************************************************************************************************/
    static void ProcessRXedData01to08(U32 RxSize)
    {
       static U8 Command01to08Byte = CMD_INVALID;
       U32 i = 0;
    
       /* Loop through all the RX data and process it. */
       for(i=0; i<RxSize; i++)
       {
          if( Command01to08Byte == CMD_INVALID )
          {
             Command01to08Byte = TCP01to08RXData[i];
             if( SingleByteCommand01to08(Command01to08Byte) == TRUE )
             {
                Command01to08Byte = CMD_INVALID;       /* All done processing this command, reset for the next one. */
             }
          }
          else
          {
             MultiByteCommand01to08(Command01to08Byte, TCP01to08RXData[i]);
             Command01to08Byte = CMD_INVALID;          /* All done processing this command, reset for the next one. */
          }
       }
    }
    
    
    /********************************************************************************************************************************/
    /*  static BOOL SingleByteCommand01to08(U8 Command)                                                                             */
    /*                                                                                                                              */
    /*  This function handles the single byte commands from the Host.                                                               */
    /*                                                                                                                              */
    /*  Parameters:                                                                                                                 */
    /*      - Command:  a command from the Host.                                                                                    */
    /*                                                                                                                              */
    /*  Returns:  TRUE = single byte command found and processed,  FALSE = multi-bye command                                        */
    /*                                                                                                                              */
    /*  Notes:  none                                                                                                                */
    /********************************************************************************************************************************/
    static BOOL SingleByteCommand01to08(U8 Command)
    {
       BOOL rc = TRUE;      /* Assume we will process a single byte command. */
    
       if( Command == CMD_HEATBEAT )
       {
          /* Load up the TX buffer with the correct response. */
          TCP01to08TXData[TCP01to08TXIndex++] = RESP_HEARTBEAT;
       }
       else if( Command == CMD_READ_SW_VERSION )
       {
          /* Load up the TX buffer with the correct response. */
          TCP01to08TXData[TCP01to08TXIndex++] = RESP_START_SW_VERSION;
          memcpy(&TCP01to08TXData[TCP01to08TXIndex], g_SWVersion, strlen(g_SWVersion));
          TCP01to08TXIndex = TCP01to08TXIndex + strlen(g_SWVersion);
          TCP01to08TXData[TCP01to08TXIndex++] = RESP_END_SW_VERSION;
       }
       else if( Command == CMD_LINEX_STATUS )
       {
          /* Load up the TX buffer with the correct response. */
          TCP01to08TXData[TCP01to08TXIndex++] = RESP_LINEX_STATUS;
          TCP01to08TXData[TCP01to08TXIndex++] = PhoneLine01to08HookStatus();
       }
       else if( Command == CMD_REQUEST_PS_STATUS )
       {
          /* Load up the TX buffer with the correct response. */
          TCP01to08TXData[TCP01to08TXIndex++] = RESP_PS_STATUS;
          TCP01to08TXData[TCP01to08TXIndex++] = (U8)(ReadPowerSupplyStatus());
       }
       else
       {
          rc = FALSE;       /* Must be a multi-byte command, keep reeling in the data. */
       }
    
       return(rc);
    }
    
    
    /********************************************************************************************************************************/
    /*  static void MultiByteCommand01to08(U8 Command, U8 RxData)                                                                   */
    /*                                                                                                                              */
    /*  This function handles the multi-byte commands from the Host.                                                                */
    /*                                                                                                                              */
    /*  Parameters:                                                                                                                 */
    /*      - Command:  a command from the Host.                                                                                    */
    /*      - RxData:  data that goes with the multi-byte command                                                                   */
    /*                                                                                                                              */
    /*  Returns:  none                                                                                                              */
    /*                                                                                                                              */
    /*  Notes:  none                                                                                                                */
    /********************************************************************************************************************************/
    static void MultiByteCommand01to08(U8 Command, U8 RxData)
    {
       PhoneLines_t PhoneLine = (PhoneLines_t)((RxData & 0x07) + 1);     /* Host sends 0-7, convert to the real phone line number. */
    
       if( Command == CMD_LINEX_OFFHOOK )
       {
          ChangePhoneHookState(PhoneLine, OFFHOOK);
          TCP01to08TXData[TCP01to08TXIndex++] = RESP_LINEX_OFFHOOK_DONE;
          TCP01to08TXData[TCP01to08TXIndex++] = (U8)(PhoneLine - 1);     /* Convert real phone line back to 0-7 for the Host. */
       }
       else if( Command == CMD_LINEX_ONHOOK )
       {
          if( ChangePhoneHookState(PhoneLine, ONHOOK) == TRUE )
          {
             TCP01to08TXData[TCP01to08TXIndex++] = RESP_LINEX_ONHOOK_DONE;
             TCP01to08TXData[TCP01to08TXIndex++] = (U8)(PhoneLine - 1);     /* Convert real phone line back to 0-7 for the Host. */
          }
          else
          {
             TCP01to08TXData[TCP01to08TXIndex++] = RESP_LINEX_ONHOOK_DONE;
             TCP01to08TXData[TCP01to08TXIndex++] = ((U8)(PhoneLine - 1)) & 0x80U;    /* Alert Host that the phone line is missing. */
          }
       }
       else if( Command == CMD_AGENT_LOGGED_IN )
       {
          UpdatePhoneLineLED(PhoneLine, LED_PHONE_OK_AGENT);
       }
       else if( Command == CMD_AGENT_LOGGED_OUT )
       {
          UpdatePhoneLineLED(PhoneLine, LED_PHONE_OK_NOAGENT);
       }
       else
       {
          /* Unknown command. */
       }
    }
    
    
    /********************************************************************************************************************************/
    /*  static void CloseConnectSocket01to08(void)                                                                                  */
    /*                                                                                                                              */
    /*  Perform a graceful shutdown of the connected socket.                                                                        */
    /*                                                                                                                              */
    /*  Parameters:                                                                                                                 */
    /*      - none                                                                                                                  */
    /*                                                                                                                              */
    /*  Returns:  none                                                                                                              */
    /*                                                                                                                              */
    /*  Notes:  none                                                                                                                */
    /********************************************************************************************************************************/
    static void CloseConnectSocket01to08(void)
    {
       shutdown(ConnectSocket1, SHUT_WR);                       /* This should send a FIN packet to the far end. */
       memset(TCP01to08RXData, NULL, sizeof(TCP01to08RXData));
       while( recv(ConnectSocket1, TCP01to08RXData, sizeof(TCP01to08RXData), 0) > 0 )
       {
          /* Keep reading data until there is nothing left, or an error has occured. */
          memset(TCP01to08RXData, NULL, sizeof(TCP01to08RXData));
       }
    
       shutdown(ConnectSocket1, SHUT_RDWR);
       fdClose(ConnectSocket1);
    }
    
    
    /********************************************************************************************************************************/
    /*  static void Check01to08Ringing(void)                                                                                        */
    /*                                                                                                                              */
    /*  Check if any of the phone lines are ringing, and report back to the host if one or more are ringing.                        */
    /*                                                                                                                              */
    /*  Parameters:                                                                                                                 */
    /*      - none                                                                                                                  */
    /*                                                                                                                              */
    /*  Returns:  none                                                                                                              */
    /*                                                                                                                              */
    /*  Notes:  none                                                                                                                */
    /********************************************************************************************************************************/
    static void Check01to08Ringing(void)
    {
       U8 LineXRinging = PhoneLine01to08RingStatus();
    
       if( LineXRinging != 0 )
       {
          TCP01to08TXData[TCP01to08TXIndex++] = RESP_LINEX_RINGING;
          TCP01to08TXData[TCP01to08TXIndex++] = LineXRinging;
       }
    }