ts-7000
[Top] [All Lists]

[ts-7000] Re: Serial to Ethernet Converter

To:
Subject: [ts-7000] Re: Serial to Ethernet Converter
From: "Fred" <>
Date: Fri, 11 Jul 2008 16:07:29 -0000
--- In  "juanyrascon" <> wrote:
>
> 
> How can i do one serial to ethernet converter with my ts7300.

// -------------------------------------------------------------------
---
// Default values:
//
//      /dev/ttyAM0             -d{value} overrides this setting
//      115200 baud             -b{value} overrides this settings
//      TCP port 10023          -t{value} overrides this setting
//      Fragile enabled         -f{yes | no} overrides this setting
//
// make CROSS_COMPILE=arm-unknown-linux-gnu-  factest
//
// -------------------------------------------------------------------
---

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <sys/mman.h>           // We seize control of memory mapped 
devices
#include "nvcore.h"             // For standard types
#include "stunnel.h"            // Always include ourself
#include "myutils.h"            // For general utility functions

// -------------------------------------------------------------------
---
// General local data storage for this process
//
// -------------------------------------------------------------------
---

    static int      mem_handle;
    static vuint8 * watchdog_feed_p;
    static vuint8 * watchdog_control_p;
    static int      module_serial_port;
    static uint8    process_kill_yourself;

// -------------------------------------------------------------------
---
// Local data storage for TCP connections
//
// -------------------------------------------------------------------
---

    static SOCKET             socket_listen;
    static SOCKET             socket_accepted;
    static struct sockaddr_in channel_listen;
    static uint8              listen_connected;
    static fd_set             read_tcp_set;

// -------------------------------------------------------------------
---
// Command line arguments can alter these values
//
// -------------------------------------------------------------------
---

    static uint8  serial_device[101];
    static uint16 baud_rate;
    static uint16 tcp_port;
    static uint8  fragile_sockets;

//--------------------------------------------------------------------
------------------------------
//  Function Name: initialize_process()
//
//    Description: This function will initialize the local data 
storage
//                 for this process.
//
// Pre-Conditions:
//
//     Parameters
//          Local: void
//
//        Globals:
//
//        Returns: void
//
//      Reference: none
//
//--------------------------------------------------------------------
------------------------------

static void initialize_process(void)
{
    // Initialize this process' data

    watchdog_feed_p       = (vuint8 *)NULL;
    watchdog_control_p    = (vuint8 *)NULL;
    module_serial_port    = 0;
    socket_listen         = (SOCKET)-1;
    socket_accepted       = (SOCKET)-1;
    listen_connected      = FALSE;
    process_kill_yourself = FALSE;

    // Get a handle on device memory

    mem_handle = open("/dev/mem", O_RDWR);

    // Create pointers to the watchdog memory
        
    watchdog_control_p = (uint8 *)mmap(0, getpagesize(),
        PROT_READ | PROT_WRITE, MAP_SHARED, mem_handle, 0x23800000);

    watchdog_feed_p = (uint8 *)mmap(0, getpagesize(),
        PROT_READ | PROT_WRITE, MAP_SHARED, mem_handle, 0x23C00000);

    // Kick and then configure the watchdog

    *watchdog_feed_p    = 0x05;
    *watchdog_control_p = 0x07;

    // Set up the default configurable items

    (void)strcpy(serial_device, DEFAULT_SERIAL_DEVICE);

    baud_rate       = DEFAULT_BAUD_RATE;
    tcp_port        = DEFAULT_TCP_PORT;
    fragile_sockets = DEFAULT_FRAGILITY;
}

//--------------------------------------------------------------------
------------------------------
//  Function Name: kick_watchdog()
//
//    Description: Kick the watchdog to keep the timer from resetting
//                 the CPU while we are working with it.
//
// Pre-Conditions:
//
//     Parameters
//          Local: void
//
//        Globals:
//
//        Returns: void
//
//      Reference: none
//
//--------------------------------------------------------------------
------------------------------

static void kick_watchdog(void)
{
    // Kick the watchdog to reset its timeout timer

    *watchdog_feed_p = 0x05;
}

//--------------------------------------------------------------------
------------------------------
//  Function Name: compute_baud()
//
//    Description: This function will take an ASCII baud rate value 
and
//                 convert it in to the Linux index value for the 
baud rate,
//                 returning the value.
//
// Pre-Conditions:
//
//     Parameters
//          Local: argument_p -- A pointer to the ASCII string which
//                 contains the baud rate that was selected on the
//                 command line.
//
//        Globals:
//
//        Returns: The Linux defined constant for the selected baud 
rate.
//
//      Reference: none
//
//--------------------------------------------------------------------
------------------------------

static uint16 compute_baud(char * argument_p)
{
    switch(atoi(argument_p))
    {
        case   1200: return(B1200);
        case   4800: return(B4800);
        case   9600: return(B9600);
        case  19200: return(B19200);
        case  38400: return(B38400);
        case  57600: return(B57600);
        case 115200: return(B115200);
        default:     return(B115200);
    }
}

//--------------------------------------------------------------------
------------------------------
//  Function Name: open_serial_interface()
//
//    Description: The seriual interface is opened and configured 
here.
//
// Pre-Conditions:
//
//     Parameters
//          Local: void
//
//        Globals:
//
//        Returns: void
//
//      Reference: none
//
//--------------------------------------------------------------------
------------------------------

static void open_serial_interface(void)
{
    struct termios newtio = { 0 };

    // Open the serial interface

    module_serial_port =
        open(serial_device, O_RDWR | O_NDELAY | O_NOCTTY, 0);

    // Set up the serial interface

    tcgetattr(module_serial_port, &newtio);

    newtio.c_cflag     = CS8 | CLOCAL | CREAD;
    newtio.c_iflag     = IGNBRK | IGNPAR;
    newtio.c_oflag     = 0;
    newtio.c_lflag     = 0;
    newtio.c_cc[VTIME] = 0;
    newtio.c_cc[VMIN]  = 0;

    cfsetispeed(&newtio, baud_rate);
    cfsetospeed(&newtio, baud_rate);

    tcsetattr(module_serial_port, TCSANOW, &newtio);

    // Discard anything being sent or received

    tcflush(module_serial_port, TCIFLUSH);
}

//--------------------------------------------------------------------
------------------------------
//  Function Name: establish_telnet_listen()
//
//    Description: A TCP listen is established on the configured TCP 
port
//                 number, and the connection is made non-blocking.
//
// Pre-Conditions:
//
//     Parameters
//          Local: void
//
//        Globals:
//
//        Returns: void
//
//      Reference: none
//
//--------------------------------------------------------------------
------------------------------

static void establish_telnet_listen(void)
{
    uint16 option = 1;

    // Create listening socket

    socket_listen = socket(AF_INET, SOCK_STREAM, 0);

    // Zero the associated control block

    (void)memset((uint8 *)&channel_listen, 0x00, sizeof
(channel_listen));

    // And set its values

    channel_listen.sin_family      = AF_INET;
    channel_listen.sin_addr.s_addr = INADDR_ANY;
    channel_listen.sin_port        = htons(tcp_port);

    // Set the listen socket for non-blocking

    myutils_set_non_blocking(socket_listen, TRUE);

    // Set socket options

    (void)setsockopt(socket_listen, SOL_SOCKET, SO_REUSEADDR,
        (char *)&option, sizeof(uint16));

    // Let's set keep alive on the socket

    option = 1;

    (void)setsockopt(socket_listen, SOL_SOCKET, SO_KEEPALIVE,
        (char *)&option, sizeof(uint16));

    // And bind the socket

    (void)bind(socket_listen,
        (struct sockaddr *)&channel_listen,
            sizeof(channel_listen));

    // Set up the listen on that

    (void)listen(socket_listen, 5);

    // We want to select() on that TCP socket we listen on

    FD_ZERO(&read_tcp_set);
}

//--------------------------------------------------------------------
------------------------------
//  Function Name: check_for_serial_data()
//
//    Description: The serial interface is checked to see if there is 
any
//                 data waiting.  If there is, it is read out and if 
there
//                 is a Telnet session established, the data is sent 
out
//                 the Telnet socket.
//
// Pre-Conditions:
//
//     Parameters
//          Local: void
//
//        Globals:
//
//        Returns: void
//
//      Reference: none
//
//--------------------------------------------------------------------
------------------------------

static void check_for_serial_data(void)
{
    uint8   in_buffer[1001] = { 0, 0 };
    int32   write_result    = 0L;
    int32   updated_count   = 0L;
    uint8 * slow_write_p    = (uint8 *)NULL;

    // Let's make sure that the serial interface is open

    if (module_serial_port == 0)
    {
        // We didn't open the device

        return;
    }

    // Get characters into our local stack buffer

    updated_count =
        read(module_serial_port, in_buffer, (sizeof(in_buffer)));

    // Are there any characters read?

    if (updated_count > 0)
    {
        // Is there a Telnet TCP connection up?

        if (TRUE == listen_connected)
        {
            // Write the serial data out the TCP connection

            slow_write_p = in_buffer;

            write_result =
                write(socket_accepted, slow_write_p, updated_count);

            // Let's confirm that the write was fully successful

            while (write_result >= 0 && write_result < updated_count)
            {
                // We must wait for room to be made

                usleep(TS72XX_USLEEP_GRANULARITY * 20);

                // Update the count remaining

                updated_count -= write_result;

                // Point to the remaining to be sent

                slow_write_p += write_result;

                // And attempt to write the remaining block

                write_result =
                    write(socket_accepted, slow_write_p, 
updated_count);
            }
        }
    }
}

//--------------------------------------------------------------------
------------------------------
//  Function Name: check_for_tcp_data()
//
//    Description: If a Telnet session is established, this function 
will
//                 read out the data and send it out the serial 
interface.
//
// Pre-Conditions:
//
//     Parameters
//          Local: void
//
//        Globals:
//
//        Returns: void
//
//      Reference: none
//
//--------------------------------------------------------------------
------------------------------

static void check_for_tcp_data(void)
{
    uint8           in_buffer[1001] = { 0, 0 };
    struct timeval  timeout         = { 0 };
    SOCKET          socket_drop     = (SOCKET)-1;
    int32           write_result    = 0L;
    int32           updated_count   = 0L;
    uint8         * slow_write_p    = (uint8 *)NULL;

    // Is the inbound TCP being listened on?  Should be.

    if ((SOCKET)-1 == socket_listen)
    {
        // We are not listening so do nothing

        (void)printf("Error: We are no longer listening\n");
        return;
    }

    // Do we currently have a connection?
        
    if (FALSE == listen_connected)
    {
        // See if it's waiting for an accept to an inbound

        timeout.tv_sec  = 0;
        timeout.tv_usec = 10;

        // Make sure that we are selecting for readability

        FD_ZERO(&read_tcp_set);

        FD_SET(socket_listen, &read_tcp_set);

        updated_count = select((socket_listen + 1),
            &read_tcp_set, NULL, NULL, &timeout);

        // Check for an error condition

        if (updated_count < 0)
        {
            return;
        }

        // Check for no read or exception

        if (updated_count == 0)
        {
            // Apparently we don't have a connection yet

            return;
        }

        // We're supposedly readable now

        if (FD_ISSET(socket_listen, &read_tcp_set))
        {
            // Accept server connection

            socket_accepted = accept(socket_listen, NULL, NULL);

            // Was the accept successful?
 
            if (socket_accepted < 0)
            {
                // We had a problem with accepting the connection

                return;
            }
            else
            {
                // Flag the fact that we're connected

                listen_connected = TRUE;

                // Set the accepted TCP connection to non-blocking

                myutils_set_non_blocking(socket_accepted, TRUE);

                (void)printf("TCP connection established\n");
            }
        }
        else
        {
            // No connection is waiting to be accepted

            return;
        }
    }
    else
    {
        // We have a connection already.  Is another pending?

        timeout.tv_sec  = 0;
        timeout.tv_usec = 10;

        // Make sure that we are selecting for readability

        FD_ZERO(&read_tcp_set);

        FD_SET(socket_listen, &read_tcp_set);

        updated_count = select((socket_listen + 1),
           &read_tcp_set, NULL, NULL, &timeout);

        // Check for no read or exception

        if (updated_count != 0)
        {
            if (FD_ISSET(socket_listen, &read_tcp_set))
            {
                // Accept that connection

                socket_drop = accept(socket_listen, NULL, NULL);

                // Let's swap processes to let that accept take

                usleep(TS72XX_USLEEP_GRANULARITY);

                // Check for fragility

                if (TRUE == fragile_sockets)
                {
                    // Adopt the new connection.  First we drop the 
old

                    (void)close(socket_accepted);

                    // Then we adopt the new socket

                    socket_accepted = socket_drop;

                    (void)printf("Secondary connection adopted, old 
dropped\n");
                }
                else
                {
                    (void)printf("Disallowed secondary connection\n");

                    // And then drop it

                    (void)close(socket_drop);
                }
            }
        }
    }

    // Verify that we have an accepted socket

    if ((SOCKET)-1 == socket_accepted)
    {
        // Something happened so we're no longer connected

        listen_connected = FALSE;

        // We can't do anything else

        return;
    }

    // Get characters into our local stack buffer

    updated_count =
        read(socket_accepted, in_buffer, (sizeof(in_buffer) - 1));

    // Check to see if the socket closed

    if (updated_count == 0)
    {
        // The socket did close on us

        listen_connected = FALSE;
        socket_accepted  = (SOCKET)-1;

        (void)printf("TCP connection has been dropped\n");

        // And we are done here

        return;
    }

    // Make sure that we got a positive byte count

    if (updated_count > 0)
    {
        // Send the TCP data out the serial interface

        slow_write_p = in_buffer;

        write_result =
            write(module_serial_port, slow_write_p, updated_count);

        // Let's confirm that the write was fully successful

        while (write_result >= 0 && write_result < updated_count)
        {
            // We must wait for room to be made

            usleep(TS72XX_USLEEP_GRANULARITY * 20);

            // Update the count remaining

            updated_count -= write_result;

            // Point to the remaining to be sent

            slow_write_p += write_result;

            // And attempt to write the remaining block

            write_result =
                write(module_serial_port, slow_write_p, 
updated_count);
        }
    }
}

//--------------------------------------------------------------------
------------------------------
//  Function Name: display_process_help_screen()
//
//    Description: The help screen for the process is displayed here.
//
// Pre-Conditions:
//
//     Parameters
//          Local: void
//
//        Globals:
//
//        Returns: void
//
//      Reference: none
//
//--------------------------------------------------------------------
------------------------------

static void display_process_help_screen(void)
{
    (void)printf("\n");
    (void)printf("This process will create a serial-to-ethernet 
tunnel so\n");
    (void)printf("that people may telnet to serial devices which are 
plugged\n");
    (void)printf("in to the Safetran product's serial interface.  You 
may\n");
    (void)printf("specify the serial interface, baud rate, the TCP 
port to\n");
    (void)printf("listen on, and whether fragile sockets is enabled 
or not.\n");
    (void)printf("\n");
    (void)printf("Default values:\n");
    (void)printf("    /dev/ttyAM0      -d{value} overrides this 
setting\n");
    (void)printf("    115200 baud      -b{value} overrides this 
settings\n");
    (void)printf("    TCP port 10023   -t{value} overrides this 
setting\n");
    (void)printf("    Fragile enabled  -f{yes | no} overrides this 
setting\n");
    (void)printf("\n");
}

//--------------------------------------------------------------------
------------------------------
//  Function Name: handle_command_arguments()
//
//    Description: This function checks to see if any command line 
arguments
//                 were received and if there were, they get handled.
//
// Pre-Conditions:
//
//     Parameters
//          Local: argc -- The number of command line arguments that
//                 were received when the process was launched
//
//                 argv -- A pointer to an array of pointers which 
point to
//                 the optional command like arguments entered when 
this
//                 process was launched
//
//        Globals:
//
//        Returns:
//
//      Reference: none
//
//--------------------------------------------------------------------
------------------------------

static void handle_command_arguments(int argc, char * * argv)
{
    uint8 * first_argument_p = (uint8 *)NULL;
    uint8   which_argument   = 0;

    // Go through any arguments passed on the command line

    for (which_argument = 1; which_argument < argc; which_argument++)
    {
        // Point to the argument

        first_argument_p = &argv[which_argument][0];

        // Discard any leading spaces or tabs

        skipspace(first_argument_p)
        {
            // Determine what the first characer of the argument is

            switch(*first_argument_p)
            {
                default:
                {
                    // It's not an argument that we understand

                    break;
                }

                case '-':
                {
                    // Discard all dashes that may exist

                    while (*first_argument_p == '-')
                    {
                        first_argument_p++;
                    }

                    // Discard any leading space or tabs

                    skipspace(first_argument_p);

                    // Find out what the argument for the switch
                    // command is and act on that command

                    switch(*first_argument_p)
                    {
                        case 'd':
                        case 'D':
                        {
                            // Point to the start of the serial device

                            first_argument_p++;

                            // Store the new serial device

                            (void)strcpy(serial_device, 
first_argument_p);
                            break;
                        }

                        case 'b':
                        case 'B':
                        {
                            // Point to the start of the baud rate

                            first_argument_p++;

                            // Extract and convert baud rate

                            baud_rate = compute_baud
(first_argument_p);
                            break;
                        }

                        case 't':
                        case 'T':
                        {
                            // Point to the start of the TCP port 
number

                            first_argument_p++;

                            // Extract the new TCP port number

                            tcp_port = atoi(first_argument_p);
                            break;
                        }

                        case 'f':
                        case 'F':
                        {
                            // Point to the start of the fragility 
setting

                            first_argument_p++;

                            // See if there is a valid boolean

                            if (! my_strnicmp
(first_argument_p, "yes", 3))
                            {
                                fragile_sockets = TRUE;
                            }
                            else if (! my_strnicmp
(first_argument_p, "no", 2))
                            {
                                fragile_sockets = FALSE;
                            }
                            else if (! my_strnicmp
(first_argument_p, "true", 4))
                            {
                                fragile_sockets = TRUE;
                            }
                            else if (! my_strnicmp
(first_argument_p, "false", 5))
                            {
                                fragile_sockets = FALSE;
                            }

                            break;
                        }

                        case 'h':
                        case 'H':
                        {
                            // Display some helpful information

                            display_process_help_screen();

                            // Since it was only a help request, exit

                            exit(0);

                            // Should never get to this point

                            break;
                        }

                        default:
                        {
                            // It's not a switch statement that we
                            // understand so pretty much ignore it.

                            break;
                        }
                    }
                }
            }
        }
    }
}

//--------------------------------------------------------------------
------------------------------
//  Function Name: main()
//
//    Description: This is the main entry point for the serial tunnel.
//
// Pre-Conditions:
//
//     Parameters
//          Local: argc -- The number of arguments passed to this 
process
//
//                 argv -- A pointer to an array or pointers which 
point
//                 to optional arguments passed to this process
//
//        Globals:
//
//        Returns: An error code or 0
//
//      Reference: none
//
//--------------------------------------------------------------------
------------------------------

int main(int argc, char * * argv)
{
    // Initialize this process and select default values

    initialize_process();

    // Check to see if command line arguments will be altering the
    // way we do things here.

    handle_command_arguments(argc, argv);

    kick_watchdog();

    // Acquire the serial interface

    open_serial_interface();

    // Set up the listen on the TCP port

    establish_telnet_listen();

    // This process goes into a forever loop

    while(! process_kill_yourself)
    {
        // Let some other process have control for 20ms

        usleep(TS72XX_USLEEP_GRANULARITY);

        // See if there is serial data waiting

        check_for_serial_data();

        // See if there is TCP data waiting

        check_for_tcp_data();
    }

    // Should never be able to get to this point

    return(0);
}

// End of file

// -------------------------------------------------------------------
---
// stunnel.h
//
// -------------------------------------------------------------------
---

#ifndef STUNNEL_H
#define STUNNEL_H       1

// -------------------------------------------------------------------
---
// Defined constants which we will use
//
// -------------------------------------------------------------------
---

#define DEFAULT_SERIAL_DEVICE   "/dev/ttyAM0"
#define DEFAULT_BAUD_RATE       B115200
#define DEFAULT_TCP_PORT        10023
#define DEFAULT_FRAGILITY       TRUE

#endif

// End of file



------------------------------------

Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/ts-7000/

<*> Your email settings:
    Individual Email | Traditional

<*> To change settings online go to:
    http://groups.yahoo.com/group/ts-7000/join
    (Yahoo! ID required)

<*> To change settings via email:
     
    

<*> To unsubscribe from this group, send an email to:
    

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/

<Prev in Thread] Current Thread [Next in Thread>
Admin

Disclaimer: Neither Andrew Taylor nor the University of NSW School of Computer and Engineering take any responsibility for the contents of this archive. It is purely a compilation of material sent by many people to the birding-aus mailing list. It has not been checked for accuracy nor its content verified in any way. If you wish to get material removed from the archive or have other queries about the archive e-mail Andrew Taylor at this address: andrewt@cse.unsw.EDU.AU