/*********************************************************************************
|
* Copyright: (C) 2021 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(5/1/2021~)
|
* Author: Guo Wenxue <guowenxue@gmail.com>
|
* ChangeLog: 1, Release initial version on "5/1/2021 10:08:05 AM"
|
*
|
********************************************************************************/
|
#include <getopt.h>
|
#include <libgen.h>
|
#include <sys/ioctl.h>
|
|
#include "comport.h"
|
|
unsigned char g_stop = 0;
|
unsigned char g_CtrlZ;
|
|
void print_version(char *name);
|
void usage(char *name);
|
void signal_handler(int i_sig);
|
void stdin_nonblock(void);
|
int kbhit(void);
|
|
|
int main(int argc, char **argv)
|
{
|
int opt = 0;
|
int rv = 0;
|
int i;
|
|
comport_t comport;
|
int baudrate = 115200;
|
char *settings = "8N1N";
|
char *dev_name = NULL;
|
|
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'},
|
{"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:vh", 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 '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;
|
}
|
|
if ( (rv=comport_open(&comport, dev_name, baudrate, settings)) < 0)
|
{
|
printf("Failed to open %s wth baudrate %d, %s. rv=%d\n", dev_name, baudrate, settings, rv);
|
return -1;
|
}
|
|
stdin_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 ( !g_stop )
|
{
|
rv = comport_recv(&comport, buf, sizeof(buf) - 1, 10);
|
if ( rv > 0)
|
{
|
for (i=0; i<rv ; i++)
|
{
|
if (0 == disp_mode)
|
printf("%c", buf[i]);
|
else
|
printf("%02X ", buf[i]);
|
}
|
fflush(stdout);
|
}
|
if (0 != kbhit())
|
{
|
rv = fgetc(stdin);
|
|
if (0x0A == rv)
|
{
|
buf[0] = 0x0D; /* 13 == 0x0D */
|
}
|
else
|
{
|
buf[0] = rv;
|
}
|
|
comport_send(&comport, buf, 1);
|
}
|
else if (0x00 != g_CtrlZ)
|
{
|
g_CtrlZ = 0x00;
|
buf[0] = 0x1A;
|
comport_send(&comport, buf, 1);
|
}
|
}
|
|
comport_close(&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 v1.0.0 Build on %s\n", progname, __DATE__);
|
printf("Copyright (C) 2021 guowenxue <guowenxue@gmail.com>\n");
|
|
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(" -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(" -v[version ] Display the program version\n");
|
printf(" -h[help ] Display this help information\n");
|
print_version(progname);
|
|
free(ptr);
|
|
return;
|
}
|
|
|
void signal_handler(int signum)
|
{
|
if (SIGTERM == signum || SIGINT == signum)
|
{
|
g_stop = 1;
|
}
|
else if (SIGTSTP == signum)
|
{
|
g_CtrlZ = 1;
|
}
|
}
|
|
|
void stdin_nonblock(void)
|
{
|
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(void)
|
{
|
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);
|
}
|