From fc4b2a81273f6eac85897fce3ec049ee39b92bce Mon Sep 17 00:00:00 2001
From: Guo Wenxue <guowenxue@gmail.com>
Date: Mon, 29 Oct 2018 08:33:06 +0800
Subject: [PATCH] Add comport program

---
 modules/c/comport/cp_common.h  |   68 ++++
 modules/c/comport/makefile     |    8 
 modules/c/comport/cp_comport.h |   67 +++
 modules/c/comport/cp_comport.c |  600 +++++++++++++++++++++++++++++++++++
 modules/c/comport/comport.c    |  237 +++++++++++++
 5 files changed, 980 insertions(+), 0 deletions(-)

diff --git a/modules/c/comport/comport.c b/modules/c/comport/comport.c
new file mode 100644
index 0000000..7707193
--- /dev/null
+++ b/modules/c/comport/comport.c
@@ -0,0 +1,237 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2012 Guo Wenxue <guowenxue@gmail.com> 
+ *                  All rights reserved.
+ *
+ *       Filename:  comport.c
+ *    Description:  This file used to do ioctl() on common device or communicate 
+ *                  with serial port/TTY device.
+ *                 
+ *        Version:  1.0.0(10/18/2011~)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "10/18/2011 10:08:05 AM"
+ *                 
+ ********************************************************************************/
+#include <getopt.h>
+#include <libgen.h>
+#include <sys/ioctl.h>
+
+#include "cp_comport.h"
+#include "cp_common.h"
+
+unsigned char g_ucProcToken = 0x01;
+unsigned char g_ucCtrlZ;
+
+void print_version(char *name);
+void usage(char *name);
+int do_ioctl(char *dev_name, int cmd, int arg);
+void signal_handler(int i_sig);
+
+int main(int argc, char **argv)
+{
+    int opt = 0;
+    int retval = 0;
+    int recv_size = 0;
+    int i;
+    char *dev_name = NULL;
+    int baudrate = 115200;
+    char *settings = "8N1N";
+    char buf[512];
+    unsigned char disp_mode = 0x00;
+
+    struct sigaction sigact;
+
+    struct option long_options[] = {
+        {"device", required_argument, NULL, 'd'},
+        {"baudrate", required_argument, NULL, 'b'},
+        {"settings", required_argument, NULL, 's'},
+        {"ioctl", required_argument, NULL, 'i'},
+        {"hex", no_argument, NULL, 'x'},
+        {"version", no_argument, NULL, 'v'},
+        {"help", no_argument, NULL, 'h'},
+        {NULL, 0, NULL, 0}
+    };
+
+    while ((opt = getopt_long(argc, argv, "d:b:s:ivh", long_options, NULL)) != -1)
+    {
+        switch (opt)
+        {
+          case 'd':
+              dev_name = optarg;
+              break;
+          case 'b':
+              baudrate = atoi(optarg);
+              break;
+          case 's':            /* Default settings as 8N1N */
+              settings = optarg;
+              break;
+          case 'i':
+              if (5 != argc)
+              {
+                  usage(argv[0]);
+              }
+              else
+              {
+                  do_ioctl(argv[2], atoi(argv[3]), atoi(argv[4]));
+              }
+              return 0;
+          case 'x':            /* Display receive data as Hex mode */
+              disp_mode = 0x01;
+              break;
+          case 'v':            /* version */
+              print_version(argv[0]);
+              return 0;
+          case 'h':            /* help */
+              usage(argv[0]);
+              return 0;
+          default:
+              break;
+        }                       /* end of "switch(opt)" */
+    }
+
+    if (argc < 2)
+    {
+        usage(argv[0]);
+        return 0;
+    }
+
+    COM_PORT *comport = NULL;
+    if (NULL == (comport = comport_init(dev_name, baudrate, settings)))
+    {
+        printf("Comport initialize failure.\n");
+        return -1;
+    }
+
+    if ( (retval=comport_open(comport)) < 0)
+    {
+        printf("Failed to open %s with baudrate %d, %s. RetCode [%d]\n", dev_name, baudrate,
+               settings, retval);
+        return -1;
+    }
+
+    nonblock();
+
+    /* Process level signal handler */
+    sigemptyset(&sigact.sa_mask);
+    sigact.sa_flags = 0;
+    sigact.sa_handler = signal_handler;
+
+    sigaction(SIGTERM, &sigact, NULL);  /* catch terminate signal */
+    sigaction(SIGINT, &sigact, NULL);   /* catch interrupt signal */
+    sigaction(SIGSEGV, &sigact, NULL);  /* catch segmentation faults */
+    sigaction(SIGTSTP, &sigact, NULL);  /* catch ctrl+Z */
+    sigaction(SIGSTOP, &sigact, NULL);  /* catch ctrl+Z */
+
+    while (0x01 == g_ucProcToken)
+    {
+        recv_size = comport_recv(comport, buf, sizeof(buf) - 1, 10);
+        if (recv_size > 0)
+        {
+            for (i = 0; i < recv_size; i++)
+            {
+                if (0 == disp_mode)
+                    printf("%c", buf[i]);
+                else
+                    printf("%02X ", buf[i]);
+            }
+            fflush(stdout);
+        }
+        if (0 != kbhit())
+        {
+            retval = fgetc(stdin);
+
+            if (0x0A == retval)
+            {
+                buf[0] = 0x0D; /* 13 == 0x0D */
+            }
+            else
+            {
+                buf[0] = retval;
+            }
+
+            comport_send(comport, buf, 1);
+        }
+        else if (0x00 != g_ucCtrlZ)
+        {
+            g_ucCtrlZ = 0x00;
+            buf[0] = 0x1A;
+            comport_send(comport, buf, 1);
+        }
+    }
+
+    comport_term(comport);
+    return 0;
+}                               /* ----- End of main() ----- */
+
+void print_version(char *name)
+{
+    char *progname = NULL;
+    char *ptr = NULL;
+
+    ptr = strdup(name);
+    progname = basename(ptr);
+
+    printf("%s version: 1.0.0 Build %04d on %s\n", progname, __DATE__);
+    printf("Copyright (C) 2010 guowenxue <guowenxue@gmail.com>\n");
+
+    t_free(ptr);
+    return;
+}
+
+void usage(char *name)
+{
+    char *progname = NULL;
+    char *ptr = NULL;
+
+    ptr = strdup(name);
+    progname = basename(ptr);
+    printf("Usage1: comport -d <device> [-b <baudrate>][-s <settings>] [-x]\n");
+    printf("Usage2: comport [-i <driver port> <cmd> <arg>][--help][--version]\n");
+    printf(" -d[device  ]  device name\n");
+    printf(" -b[baudrate]  device baudrate (115200, 57600, 19200, 9600), default is 115200\n");
+    printf(" -s[settings]  device settings as like 8N1N(default setting)\n");
+    printf("                 - data bits: 8, 7\n");
+    printf("                 - parity: N=None, O=Odd, E=Even, S=Space\n");
+    printf("                 - stop bits: 1, 0\n");
+    printf("                 - flow control: N=None, H=Hardware, S=Software, B=Both\n");
+    printf(" -x[hex     ]  display received data in hex format\n");
+    printf(" -i[ioctl   ]  ioctl system call (cmd & arg only support int)\n");
+    printf(" -v[version ]  Display the program version\n");
+    printf(" -h[help    ]  Display this help information\n");
+
+    print_version(progname);
+
+    t_free(ptr);
+
+    return;
+}
+
+int do_ioctl(char *dev_name, int cmd, int arg)
+{
+    int fd = -1;
+    int retval = -1;
+    if (((fd = open(dev_name, O_RDWR)) < 0))
+    {
+        printf("Open device \"%s\" failure: %s\n", dev_name, strerror(errno));
+        return -1;
+    }
+
+    retval = ioctl(fd, cmd, arg);
+    printf("ioctl (%s, %d, %d) returned %d\n", dev_name, cmd, arg, retval);
+
+    close(fd);
+    return retval;
+}
+
+void signal_handler(int i_sig)
+{
+    if (SIGTERM == i_sig || SIGINT == i_sig)
+    {
+        g_ucProcToken = 0x00;
+    }
+    else if (20 == i_sig)
+    {
+        g_ucCtrlZ = 0x01;
+    }
+}
+
+
diff --git a/modules/c/comport/cp_common.h b/modules/c/comport/cp_common.h
new file mode 100644
index 0000000..2aae14a
--- /dev/null
+++ b/modules/c/comport/cp_common.h
@@ -0,0 +1,68 @@
+/********************************************************************************
+ *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
+ *                  All rights reserved.
+ *
+ *       Filename:  cp_common.h
+ *    Description:  This head file is for some common definition
+ *
+ *        Version:  1.0.0(11/13/2012~)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "11/13/2012 01:48:01 PM"
+ *                 
+ ********************************************************************************/
+
+#ifndef __CP_COMMON_H
+#define __CP_COMMON_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+#define container_of(ptr, type, member) ({   \
+        const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+        (type *)( (char *)__mptr - offsetof(type,member) );})
+
+//#define MEM_LEAK_CHECK
+
+static inline void *_t_malloc(size_t size
+#ifdef MEM_LEAK_CHECK
+, const char *file, unsigned int line
+#endif
+        )
+{
+    void *ptr;
+    
+    if ((ptr = malloc (size)))
+        memset (ptr, 0, size);
+#ifdef MEM_LEAK_CHECK
+    printf ("MALLOC,0x%p @%s:%u\n", ptr, file, line);
+#endif
+    return ptr;
+}
+
+static inline void _t_free(void *ptr
+#ifdef MEM_LEAK_CHECK
+, const char *file, unsigned int line
+#endif
+        )
+{
+#ifdef MEM_LEAK_CHECK
+    printf ("FREE,0x%p @%s:%u\n", ptr, file, line);
+#endif
+    free(ptr);
+}
+
+#ifdef MEM_LEAK_CHECK
+#define t_free(p)    if(p){ _t_free(p, __FILE__, __LINE__); p=NULL; }
+#define t_malloc(s)  _t_malloc(s, __FILE__, __LINE__)
+#else
+#define t_free(p)    if(p){ _t_free(p); p=NULL; }
+#define t_malloc(s)  _t_malloc(s)
+#endif
+
+#endif
+
diff --git a/modules/c/comport/cp_comport.c b/modules/c/comport/cp_comport.c
new file mode 100644
index 0000000..b18596a
--- /dev/null
+++ b/modules/c/comport/cp_comport.c
@@ -0,0 +1,600 @@
+/*  ********************************************************************************
+ *      Copyright:  (C) 2012 Guo Wenxue <guowenxue@gmail.com>
+ *                  All rights reserved.
+ *
+ *       Filename:  cp_comport.c
+ *    Description:  It's the comport operate library.
+ *                  
+ *        Version:  1.0.0(10/17/2011~)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "10/17/2011 03:33:25 PM"
+ *                  
+ ********************************************************************************/
+
+#include    "cp_comport.h"
+
+/**************************************************************************************
+ *  Description: Set the comport structure
+ *   Input Args: dev_name:  The comport device name path, such as '/dev/ttyS3'
+ *               baudrate:  The baudrate, such as 115200
+ *               settings:  The databit,parity,stopbit,flowctrl settings, such as '8N1N'
+ *  Output Args: NONE
+ * Return Value: The COM_PORT structure pointer.
+ *************************************************************************************/
+COM_PORT *comport_init(const char *dev_name, int baudrate, const char *settings)
+{
+    COM_PORT *comport = NULL;
+    if (NULL == (comport = (COM_PORT *) malloc(sizeof(COM_PORT))))
+    {
+        return NULL;
+    }
+    memset(comport, 0, sizeof(COM_PORT));
+    comport->is_connted = 0;
+    comport->frag_size = 128;
+
+    strncpy(comport->dev_name, dev_name, DEVNAME_LEN);
+    comport->baudrate = baudrate;
+
+    set_settings(comport, settings);
+#ifdef  COM_DEBUG
+    disp_settings(comport);
+#endif
+
+    return comport;
+}
+
+#ifdef  COM_DEBUG
+void disp_settings(COM_PORT * comport)
+{
+    COM_PRINT("Device:\t\t\t\"%s\"\n", comport->dev_name);
+    COM_PRINT("Baudrate:\t\t%ld\n", comport->baudrate);
+    COM_PRINT("DataBit:\t\t\'%d\'\n", comport->databit);
+    switch (comport->parity)
+    {
+      case 0:
+          COM_PRINT("Parity:\t\t\t\'N\'\n");
+          break;
+      case 1:
+          COM_PRINT("Parity:\t\t\t\'O\'\n");
+          break;
+      case 2:
+          COM_PRINT("Parity:\t\t\t\'E\'\n");
+          break;
+      case 3:
+          COM_PRINT("Parity:\t\t\t\'S\'\n");
+          break;
+    }
+    COM_PRINT("StopBit:\t\t\'%ld\'\n", (long int)comport->stopbit);
+    switch (comport->flowctrl)
+    {
+      case 0:
+          COM_PRINT("FlowCtrl:\t\t\'N\'\n");
+          break;
+      case 1:
+          COM_PRINT("FlowCtrl:\t\t\'S\'\n");
+          break;
+      case 2:
+          COM_PRINT("FlowCtrl:\t\t\'H\'\n");
+          break;
+      case 3:
+          COM_PRINT("FlowCtrl:\t\t\'B\'\n");
+          break;
+    }
+    COM_PRINT("\n");
+    return;
+}
+#endif
+
+/**************************************************************************************
+ *  Description: Set the comport databit,parity,stopbit,flowctrl
+ *   Input Args: comport: the COM_PORT pointer
+ *               settings: The databit/parity/stopbit/flowctrl settings as like "8N1N" 
+ *  Output Args: NONE
+ * Return Value: NONE
+ *************************************************************************************/
+void set_settings(COM_PORT * comport, const char *settings)
+{
+    if(NULL==settings || NULL==comport)
+        return ;
+
+    switch (settings[0])        /* data bit */
+    {
+      case '7':
+          comport->databit = 7;
+          break;
+      case '8':
+      default:
+          comport->databit = 8;
+          break;
+    }
+
+    switch (settings[1])        /* parity */
+    {
+      case 'O':
+      case 'o':
+          comport->parity = 1;
+          break;
+      case 'E':
+      case 'e':
+          comport->parity = 2;
+          break;
+      case 'S':
+      case 's':
+          comport->parity = 3;
+          break;
+      case 'N':
+      case 'n':
+      default:
+          comport->parity = 0;
+          break;
+    }
+
+    switch (settings[2])        /* stop bit */
+    {
+      case '0':
+          comport->stopbit = 0;
+          break;
+      case '1':
+      default:
+          comport->stopbit = 1;
+          break;
+    }
+
+    switch (settings[3])        /* flow control */
+    {
+      case 'S':
+      case 's':
+          comport->flowctrl = 1;
+          break;
+      case 'H':
+      case 'h':
+          comport->flowctrl = 2;
+          break;
+      case 'B':
+      case 'b':
+          comport->flowctrl = 3;
+          break;
+      case 'N':
+      case 'n':
+      default:
+          comport->flowctrl = 0;
+          break;
+    }
+}
+
+void comport_close(COM_PORT * comport)
+{
+    if (0 != comport->fd)
+    {
+        COM_PRINT("Close device \"%s\"\n", comport->dev_name);
+        close(comport->fd);
+    }
+    comport->is_connted = 0x00;
+    comport->fd = -1;
+}
+
+void comport_term(COM_PORT * comport)
+{
+    if(NULL == comport)
+        return;
+
+    if (0 != comport->fd)
+    {
+        comport_close(comport);
+    }
+    memset(comport, 0x00, sizeof(COM_PORT)); 
+    free(comport);
+    comport = NULL;
+
+    return;
+}
+
+int comport_open(COM_PORT * comport)
+{
+    int retval = -1;
+    struct termios old_cfg, new_cfg;
+    int old_flags;
+    long tmp;
+
+    if(NULL==comport)
+        return -1;
+
+    comport_close(comport);
+
+
+    /* Not a TTY device */
+    if( !strstr(comport->dev_name, "tty"))
+    {
+        COM_PRINT("Open Not tty device \"%s\"\n", comport->dev_name);
+        comport->fd = open(comport->dev_name, O_RDWR);
+        retval = comport->fd<0 ? -2 : comport->fd;
+        goto CleanUp;
+    }
+
+    comport->fd = open(comport->dev_name, O_RDWR | O_NOCTTY | O_NONBLOCK);
+    if (comport->fd < 0)
+    {
+        retval = -3;
+        goto CleanUp;
+    }
+    COM_PRINT("Open device \"%s\"\n", comport->dev_name);
+
+    if ((-1 != (old_flags = fcntl(comport->fd, F_GETFL, 0)))
+        && (-1 != fcntl(comport->fd, F_SETFL, old_flags & ~O_NONBLOCK)))
+    {
+        // Flush input and output
+        if (-1 == tcflush(comport->fd, TCIOFLUSH))
+        {
+            retval = -4;
+            goto CleanUp;
+        }
+    }
+    else                        // Failure
+    {
+        retval = -5;
+        goto CleanUp;
+    }
+
+    if (0 != tcgetattr(comport->fd, &old_cfg))
+    {
+        retval = -6;          // Failed to get Com settings  
+        goto CleanUp;
+    }
+
+    memset(&new_cfg, 0, sizeof(new_cfg));
+
+    /*=====================================*/
+    /*       Configure comport         */
+    /*=====================================*/
+
+    new_cfg.c_cflag &= ~CSIZE;
+    new_cfg.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
+    new_cfg.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
+    new_cfg.c_oflag &= ~(OPOST);
+
+    /* Set the data bit */
+    switch (comport->databit)
+    {
+      case 0x07:
+          new_cfg.c_cflag |= CS7;
+          break;
+      case 0x06:
+          new_cfg.c_cflag |= CS6;
+          break;
+      case 0x05:
+          new_cfg.c_cflag |= CS5;
+          break;
+      default:
+          new_cfg.c_cflag |= CS8;
+          break;
+    }
+
+    /* Set the parity */
+    switch (comport->parity)
+    {
+      case 0x01:               // Odd  
+          new_cfg.c_cflag |= (PARENB | PARODD);
+          new_cfg.c_cflag |= (INPCK | ISTRIP);
+          break;
+      case 0x02:               // Even 
+          new_cfg.c_cflag |= PARENB;
+          new_cfg.c_cflag &= ~PARODD;;
+          new_cfg.c_cflag |= (INPCK | ISTRIP);
+          break;
+      case 0x03:
+          new_cfg.c_cflag &= ~PARENB;
+          new_cfg.c_cflag &= ~CSTOPB;
+          break;
+      default:
+          new_cfg.c_cflag &= ~PARENB;
+    }
+
+    /* Set Stop bit */
+    if (0x01 != comport->stopbit)
+    {
+        new_cfg.c_cflag |= CSTOPB;
+    }
+    else
+    {
+        new_cfg.c_cflag &= ~CSTOPB;
+    }
+
+    /* Set flow control */
+    switch (comport->flowctrl)
+    {
+      case 1:                  // Software control 
+      case 3:
+          new_cfg.c_cflag &= ~(CRTSCTS);
+          new_cfg.c_iflag |= (IXON | IXOFF);
+          break;
+      case 2:                  // Hardware control
+          new_cfg.c_cflag |= CRTSCTS;   // Also called CRTSCTS
+          new_cfg.c_iflag &= ~(IXON | IXOFF);
+          break;
+      default:                 // NONE
+          new_cfg.c_cflag &= ~(CRTSCTS);
+          new_cfg.c_iflag &= ~(IXON | IXOFF);
+          break;
+    }
+
+    /* Set baudrate */
+    switch (comport->baudrate)
+    {
+      case 115200:
+          tmp = B115200;
+          break;
+      case 57600:
+          tmp = B57600;
+          break;
+      case 38400:
+          tmp = B38400;
+          break;
+      case 19200:
+          tmp = B19200;
+          break;
+      case 9600:
+          tmp = B9600;
+          break;
+      case 4800:
+          tmp = B4800;
+          break;
+      case 2400:
+          tmp = B2400;
+          break;
+      case 1800:
+          tmp = B1800;
+          break;
+      case 1200:
+          tmp = B1200;
+          break;
+      case 600:
+          tmp = B600;
+          break;
+      case 300:
+          tmp = B300;
+          break;
+      case 200:
+          tmp = B200;
+          break;
+      case 150:
+          tmp = B150;
+          break;
+      case 134:
+          tmp = B134;
+          break;
+      case 110:
+          tmp = B110;
+          break;
+      case 75:
+          tmp = B75;
+          break;
+      case 50:
+          tmp = B50;
+          break;
+      default:
+          tmp = B115200;
+    }
+    cfsetispeed(&new_cfg, tmp);
+    cfsetispeed(&new_cfg, tmp);
+
+    /* Set the Com port timeout settings */
+    new_cfg.c_cc[VMIN] = 0;
+    new_cfg.c_cc[VTIME] = 0;
+
+    tcflush(comport->fd, TCIFLUSH);
+    if (0 != tcsetattr(comport->fd, TCSANOW, &new_cfg))
+    {
+        retval = -7;          // Failed to set device com port settings   
+        goto CleanUp;
+    }
+
+    COM_PRINT("Connected device \"%s\".\n", comport->dev_name);
+    comport->is_connted = 0x01;
+    retval = comport->fd;
+
+CleanUp:
+    COM_PRINT("Open device \"%s\" %s.\n", comport->dev_name, retval>0 ? "successfully" : "failure");
+    return retval;
+}
+
+void nonblock()
+{
+    struct termios ttystate;
+
+    //get the terminal state
+    tcgetattr(STDIN_FILENO, &ttystate);
+
+    //turn off canonical mode
+    ttystate.c_lflag &= ~ICANON;
+    //minimum of number input read.
+    ttystate.c_cc[VMIN] = 1;
+
+    //set the terminal attributes.
+    tcsetattr(STDIN_FILENO, TCSANOW, &ttystate);
+}
+
+int kbhit()
+{
+    struct timeval tv;
+    fd_set fds;
+    tv.tv_sec = 0;
+    tv.tv_usec = 0;
+    FD_ZERO(&fds);
+    FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0
+    select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv);
+    return FD_ISSET(STDIN_FILENO, &fds);
+}
+
+int comport_recv(COM_PORT * comport, char *buf, int buf_size, unsigned long timeout)
+{
+    int retval = 0;             // Function return value
+    int iRet;
+    fd_set stReadFds, stExcpFds;
+    struct timeval stTime;
+
+    if (NULL == buf || 0 >= buf_size)
+    {
+        COM_PRINT("%s() usage error.\n", __FUNCTION__);
+        retval = -1;
+        goto CleanUp;
+    }
+
+    if (0x01 != comport->is_connted)
+    {
+        COM_PRINT("%s() comport not connected.\n", __FUNCTION__);
+        retval = -2;
+        goto CleanUp;
+    }
+
+    //printf("bufsize=%d timeout=%lu\n", buf_size, timeout);
+
+    FD_ZERO(&stReadFds);
+    FD_ZERO(&stExcpFds);
+    FD_SET(comport->fd, &stReadFds);
+    FD_SET(comport->fd, &stExcpFds);
+
+    if (0xFFFFFFFF != timeout)
+    {
+        stTime.tv_sec = (time_t) (timeout / 1000);
+        stTime.tv_usec = (long)(1000 * (timeout % 1000));
+
+        iRet = select(comport->fd + 1, &stReadFds, 0, &stExcpFds, &stTime);
+        if (0 == iRet)
+        {
+            retval = 0;         // No data in Com port buffer
+            goto CleanUp;
+        }
+        else if (0 < iRet)
+        {
+            if (0 != FD_ISSET(comport->fd, &stExcpFds))
+            {
+                retval = -6;  // Error during checking recv status    
+                COM_PRINT("Error checking recv status.\n");
+                goto CleanUp;
+            }
+
+            if (0 == FD_ISSET(comport->fd, &stReadFds))
+            {
+                retval = 0;  // No incoming data 
+                COM_PRINT("No incoming data.\n");
+                goto CleanUp;
+            }
+        }
+        else
+        {
+            if (EINTR == errno)
+            {
+                COM_PRINT("catch interrupt signal.\n");
+                retval = 0;  // Interrupted signal catched
+            }
+            else
+            {
+                COM_PRINT("Check recv status failure.\n");
+                retval = -7;  // Error during checking recv status
+            }
+
+            goto CleanUp;
+        }
+    }
+
+    usleep(10000); /* sleep for 10ms for data incoming */
+
+    // Get data from Com port
+    iRet = read(comport->fd, buf, buf_size);
+    if (0 > iRet)
+    {
+        if (EINTR == errno)
+            retval = 0;      // Interrupted signal catched
+        else
+            retval = -3;      // Failed to read Com port
+
+        goto CleanUp;
+    }
+
+#if 0
+    {
+        int   i=0;
+        printf("Receive %d bytes data: \n", iRet);
+        for(i=0; i<iRet; i++)
+        {
+            printf("0x%02x ", buf[i]);
+        }
+        printf("\n");
+    }
+#endif
+
+    retval = iRet;
+
+  CleanUp:
+    return retval;
+
+}
+
+int comport_send(COM_PORT * comport, char *buf, int send_bytes)
+{
+    char *ptr, *end;
+    int retval = 0;
+    int send = 0;
+
+    if (NULL == buf || 0 >= send_bytes)
+    {
+        COM_PRINT("%s() Usage error.\n", __FUNCTION__);
+        retval = -1;
+        goto CleanUp;
+    }
+
+    if (0x01 != comport->is_connted)    // Comport not opened ?
+    {
+        retval = -3;
+        COM_PRINT("Serail not connected.\n");
+        goto CleanUp;
+    }
+
+    //printf("Send %s with %d bytes.\n", buf, send_bytes);
+
+    // Large data, then slice them and send
+    if (comport->frag_size < send_bytes)
+    {
+        ptr = buf;
+        end = buf + send_bytes;
+
+        do
+        {
+            // Large than frag_size
+            if (comport->frag_size < (end - ptr))
+            {
+                send = write(comport->fd, ptr, comport->frag_size);
+                if (0 >= send || comport->frag_size != send)
+                {
+                    retval = -4;
+                    goto CleanUp;
+                }
+                ptr += comport->frag_size;
+            }
+            else                // Less than frag_size, maybe last fragmention.
+            {
+                send = write(comport->fd, ptr, (end - ptr));
+                if (0 >= send || (end - ptr) != send)
+                {
+                    retval = -4;
+                    goto CleanUp;
+                }
+                ptr += (end - ptr);
+            }
+        }
+        while (ptr < end);
+    }
+    else                        // The send data is not large than a fragmention.
+    {
+        send = write(comport->fd, buf, send_bytes);
+        if (0 >= send || send_bytes != send)
+        {
+            retval = -5;
+            goto CleanUp;
+        }
+    }
+
+  CleanUp:
+    return retval;
+}
+
diff --git a/modules/c/comport/cp_comport.h b/modules/c/comport/cp_comport.h
new file mode 100644
index 0000000..7d63179
--- /dev/null
+++ b/modules/c/comport/cp_comport.h
@@ -0,0 +1,67 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2012 Guo Wenxue <guowenxue@gmail.com>
+ *                  All rights reserved.
+ *
+ *       Filename:  cp_comport.h
+ *    Description:  This head file is for the common TTY/Serial port operator library 
+ *                   
+ *        Version:  1.0.0(10/17/2011~)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "10/17/2011 03:33:25 PM"
+ *                     
+ ********************************************************************************/
+#ifndef  _CP_COMPORT_H
+#define  _CP_COMPORT_H
+
+#include  <stdio.h>
+#include  <stdlib.h>
+#include  <unistd.h>
+#include  <string.h>
+#include  <getopt.h>
+#include  <fcntl.h>
+#include  <errno.h>
+#include  <termios.h>
+#include  <sys/stat.h>
+#include  <sys/wait.h>
+#include  <sys/types.h>
+#include  <sys/stat.h>
+#include  <sys/select.h>
+
+#define BUF_64  64
+
+#ifndef DEVNAME_LEN
+#define DEVNAME_LEN          64
+#endif
+
+//#define COM_DEBUG
+#ifdef  COM_DEBUG
+#define COM_PRINT(format,args...) printf(format, ##args)
+#else
+#define COM_PRINT(format,args...) do{} while(0);
+#endif
+
+//#define msleep(m)               {struct timespec cSleep; cSleep.tv_sec = 0; cSleep.tv_nsec = m * 1000; nanosleep(&cSleep, 0);}
+
+typedef struct __COM_PORT
+{
+    unsigned char databit, parity, stopbit, flowctrl, is_connted;
+    char dev_name[DEVNAME_LEN];
+    unsigned char  used;     /* This comport used or not now */
+    int fd;
+    int frag_size;
+    long baudrate;
+} COM_PORT;
+
+COM_PORT *comport_init(const char *dev_name, int baudrate, const char *settings);
+void comport_close(COM_PORT * comport);
+int comport_open(COM_PORT * comport);
+void comport_term(COM_PORT * comport);
+int comport_recv(COM_PORT * comport, char *buf, int buf_size, unsigned long timeout);
+int comport_send(COM_PORT * comport, char *buf, int send_bytes);
+
+void set_settings(COM_PORT * comport, const char *settings);
+void disp_settings(COM_PORT * comport);
+void nonblock();
+int kbhit();
+
+#endif
diff --git a/modules/c/comport/makefile b/modules/c/comport/makefile
new file mode 100644
index 0000000..f6afd73
--- /dev/null
+++ b/modules/c/comport/makefile
@@ -0,0 +1,8 @@
+
+all: clean
+	gcc *.c -o comport
+
+clean:
+	rm -f comport
+
+

--
Gitblit v1.9.1