Merge pull request #1048 from cmorty/pull/serialdump

Fix and clean up serialdump.c
This commit is contained in:
Simon Duquennoy 2015-05-15 20:12:58 +02:00
commit f45c6ad1b0
3 changed files with 219 additions and 215 deletions

View file

@ -22,4 +22,4 @@ endif
all: $(SERIALDUMP) all: $(SERIALDUMP)
$(SERIALDUMP): serialdump.c $(SERIALDUMP): serialdump.c
$(CC) -o $@ $< $(CC) -O2 -o $@ $<

Binary file not shown.

View file

@ -1,3 +1,4 @@
#define _GNU_SOURCE
#include <stdio.h> #include <stdio.h>
#include <fcntl.h> #include <fcntl.h>
#include <termios.h> #include <termios.h>
@ -6,35 +7,36 @@
#include <sys/time.h> #include <sys/time.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h>
#define BAUDRATE B57600 #define BAUDRATE B115200
#define BAUDRATE_S "57600" #define BAUDRATE_S "115200"
#ifdef linux #ifdef linux
#define MODEMDEVICE "/dev/ttyS0" #define MODEMDEVICE "/dev/ttyS0"
#else #else
#define MODEMDEVICE "/dev/com1" #define MODEMDEVICE "/dev/com1"
#endif /* linux */ #endif /* linux */
#define SLIP_END 0300 #define SLIP_END 0300
#define SLIP_ESC 0333 #define SLIP_ESC 0333
#define SLIP_ESC_END 0334 #define SLIP_ESC_END 0334
#define SLIP_ESC_ESC 0335 #define SLIP_ESC_ESC 0335
#define CSNA_INIT 0x01 #define CSNA_INIT 0x01
#define BUFSIZE 40 #define BUFSIZE 40
#define HCOLS 20 #define HCOLS 20
#define ICOLS 18 #define ICOLS 18
#define MODE_START_DATE 0 #define MODE_START_DATE 0
#define MODE_DATE 1 #define MODE_DATE 1
#define MODE_START_TEXT 2 #define MODE_START_TEXT 2
#define MODE_TEXT 3 #define MODE_TEXT 3
#define MODE_INT 4 #define MODE_INT 4
#define MODE_HEX 5 #define MODE_HEX 5
#define MODE_SLIP_AUTO 6 #define MODE_SLIP_AUTO 6
#define MODE_SLIP 7 #define MODE_SLIP 7
#define MODE_SLIP_HIDE 8 #define MODE_SLIP_HIDE 8
static unsigned char rxbuf[2048]; static unsigned char rxbuf[2048];
@ -80,7 +82,8 @@ print_hex_line(unsigned char *prefix, unsigned char *outbuf, int index)
} }
} }
int main(int argc, char **argv) int
main(int argc, char **argv)
{ {
struct termios options; struct termios options;
fd_set mask, smask; fd_set mask, smask;
@ -95,100 +98,103 @@ int main(int argc, char **argv)
unsigned char lastc = '\0'; unsigned char lastc = '\0';
int index = 1; int index = 1;
while (index < argc) { while(index < argc) {
if (argv[index][0] == '-') { if(argv[index][0] == '-') {
switch(argv[index][1]) { switch(argv[index][1]) {
case 'b': case 'b':
/* set speed */ /* set speed */
if (strcmp(&argv[index][2], "38400") == 0) { if(strcmp(&argv[index][2], "38400") == 0) {
speed = B38400; speed = B38400;
speedname = "38400"; speedname = "38400";
} else if (strcmp(&argv[index][2], "19200") == 0) { } else if(strcmp(&argv[index][2], "19200") == 0) {
speed = B19200; speed = B19200;
speedname = "19200"; speedname = "19200";
} else if (strcmp(&argv[index][2], "57600") == 0) { } else if(strcmp(&argv[index][2], "57600") == 0) {
speed = B57600; speed = B57600;
speedname = "57600"; speedname = "57600";
} else if (strcmp(&argv[index][2], "115200") == 0) { } else if(strcmp(&argv[index][2], "115200") == 0) {
speed = B115200; speed = B115200;
speedname = "115200"; speedname = "115200";
} else { } else {
fprintf(stderr, "unsupported speed: %s\n", &argv[index][2]); fprintf(stderr, "unsupported speed: %s\n", &argv[index][2]);
return usage(1); return usage(1);
} }
break; break;
case 'x': case 'x':
mode = MODE_HEX; mode = MODE_HEX;
break; break;
case 'i': case 'i':
mode = MODE_INT; mode = MODE_INT;
break; break;
case 's': case 's':
switch(argv[index][2]) { switch(argv[index][2]) {
case 'n': case 'n':
mode = MODE_SLIP_HIDE; mode = MODE_SLIP_HIDE;
break; break;
case 'o': case 'o':
mode = MODE_SLIP; mode = MODE_SLIP;
break; break;
default: default:
mode = MODE_SLIP_AUTO; mode = MODE_SLIP_AUTO;
break; break;
} }
break; break;
case 'T': case 'T':
if(strlen(&argv[index][2]) == 0) { if(strlen(&argv[index][2]) == 0) {
timeformat = "%Y-%m-%d %H:%M:%S"; timeformat = "%Y-%m-%d %H:%M:%S";
} else { } else {
timeformat = &argv[index][2]; timeformat = &argv[index][2];
} }
mode = MODE_START_DATE; mode = MODE_START_DATE;
break; break;
case 'h': case 'h':
return usage(0); return usage(0);
default: default:
fprintf(stderr, "unknown option '%c'\n", argv[index][1]); fprintf(stderr, "unknown option '%c'\n", argv[index][1]);
return usage(1); return usage(1);
} }
index++; index++;
} else { } else {
device = argv[index++]; device = argv[index++];
if (index < argc) { if(index < argc) {
fprintf(stderr, "too many arguments\n"); fprintf(stderr, "too many arguments\n");
return usage(1); return usage(1);
} }
} }
} }
fprintf(stderr, "connecting to %s (%s)", device, speedname); fprintf(stderr, "connecting to %s (%s)", device, speedname);
#ifndef __APPLE__ #ifdef O_SYNC
fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_DIRECT | O_SYNC ); fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_DIRECT | O_SYNC);
if(fd < 0 && errno == EINVAL){ // O_SYNC not supported (e.g. raspberian)
fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_DIRECT);
}
#else #else
fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_SYNC ); fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_SYNC );
#endif #endif
if (fd <0) { if(fd < 0) {
fprintf(stderr, "\n"); fprintf(stderr, "\n");
perror(device); perror("open");
exit(-1); exit(-1);
} }
fprintf(stderr, " [OK]\n"); fprintf(stderr, " [OK]\n");
if (fcntl(fd, F_SETFL, 0) < 0) { if(fcntl(fd, F_SETFL, 0) < 0) {
perror("could not set fcntl"); perror("could not set fcntl");
exit(-1); exit(-1);
} }
if (tcgetattr(fd, &options) < 0) { if(tcgetattr(fd, &options) < 0) {
perror("could not get options"); perror("could not get options");
exit(-1); exit(-1);
} }
/* fprintf(stderr, "serial options set\n"); */ /* fprintf(stderr, "serial options set\n"); */
cfsetispeed(&options, speed); cfsetispeed(&options, speed);
cfsetospeed(&options, speed); cfsetospeed(&options, speed);
/* Enable the receiver and set local mode */ /* Enable the receiver and set local mode */
options.c_cflag |= (CLOCAL | CREAD); options.c_cflag |= (CLOCAL | CREAD);
/* Mask the character size bits and turn off (odd) parity */ /* Mask the character size bits and turn off (odd) parity */
options.c_cflag &= ~(CSIZE|PARENB|PARODD); options.c_cflag &= ~(CSIZE | PARENB | PARODD);
/* Select 8 data bits */ /* Select 8 data bits */
options.c_cflag |= CS8; options.c_cflag |= CS8;
@ -197,30 +203,29 @@ int main(int argc, char **argv)
/* Raw output */ /* Raw output */
options.c_oflag &= ~OPOST; options.c_oflag &= ~OPOST;
if (tcsetattr(fd, TCSANOW, &options) < 0) { if(tcsetattr(fd, TCSANOW, &options) < 0) {
perror("could not set options"); perror("could not set options");
exit(-1); exit(-1);
} }
/* Make read() return immediately */ /* Make read() return immediately */
/* if (fcntl(fd, F_SETFL, FNDELAY) < 0) { */ /* if (fcntl(fd, F_SETFL, FNDELAY) < 0) { */
/* perror("\ncould not set fcntl"); */ /* perror("\ncould not set fcntl"); */
/* exit(-1); */ /* exit(-1); */
/* } */ /* } */
FD_ZERO(&mask); FD_ZERO(&mask);
FD_SET(fd, &mask); FD_SET(fd, &mask);
FD_SET(fileno(stdin), &mask); FD_SET(fileno(stdin), &mask);
index = 0; index = 0;
for (;;) { for(;;) {
smask = mask; smask = mask;
nfound = select(FD_SETSIZE, &smask, (fd_set *) 0, (fd_set *) 0, nfound = select(FD_SETSIZE, &smask, (fd_set *) 0, (fd_set *) 0, (struct timeval *) 0);
(struct timeval *) 0);
if(nfound < 0) { if(nfound < 0) {
if (errno == EINTR) { if(errno == EINTR) {
fprintf(stderr, "interrupted system call\n"); fprintf(stderr, "interrupted system call\n");
continue; continue;
} }
/* something is very wrong! */ /* something is very wrong! */
perror("select"); perror("select");
@ -230,143 +235,142 @@ int main(int argc, char **argv)
if(FD_ISSET(fileno(stdin), &smask)) { if(FD_ISSET(fileno(stdin), &smask)) {
/* data from standard in */ /* data from standard in */
int n = read(fileno(stdin), buf, sizeof(buf)); int n = read(fileno(stdin), buf, sizeof(buf));
if (n < 0) { if(n < 0) {
perror("could not read"); perror("could not read");
exit(-1); exit(-1);
} else if (n > 0) { } else if(n > 0) {
/* because commands might need parameters, lines needs to be /* because commands might need parameters, lines needs to be
separated which means the terminating LF must be sent */ separated which means the terminating LF must be sent */
/* while(n > 0 && buf[n - 1] < 32) { */ /* while(n > 0 && buf[n - 1] < 32) { */
/* n--; */ /* n--; */
/* } */ /* } */
if(n > 0) { if(n > 0) {
int i; int i;
/* fprintf(stderr, "SEND %d bytes\n", n);*/ /* fprintf(stderr, "SEND %d bytes\n", n);*/
/* write slowly */ /* write slowly */
for (i = 0; i < n; i++) { for(i = 0; i < n; i++) {
if (write(fd, &buf[i], 1) <= 0) { if(write(fd, &buf[i], 1) <= 0) {
perror("write"); perror("write");
exit(1); exit(1);
} else { } else {
fflush(NULL); fflush(NULL);
usleep(6000); usleep(6000);
} }
} }
} }
} else { } else {
/* End of input, exit. */ /* End of input, exit. */
exit(0); exit(0);
} }
} }
if(FD_ISSET(fd, &smask)) { if(FD_ISSET(fd, &smask)) {
int i, j, n = read(fd, buf, sizeof(buf)); int i, j, n = read(fd, buf, sizeof(buf));
if (n < 0) { if(n < 0) {
perror("could not read"); perror("could not read");
exit(-1); exit(-1);
} }
for(i = 0; i < n; i++) { for(i = 0; i < n; i++) {
switch(mode) { switch(mode) {
case MODE_START_TEXT: case MODE_START_TEXT:
case MODE_TEXT: case MODE_TEXT:
printf("%c", buf[i]); printf("%c", buf[i]);
break; break;
case MODE_START_DATE: { case MODE_START_DATE: {
time_t t; time_t t;
t = time(&t); t = time(&t);
strftime(outbuf, HCOLS, timeformat, localtime(&t)); strftime(outbuf, HCOLS, timeformat, localtime(&t));
printf("%s|", outbuf); printf("%s|", outbuf);
mode = MODE_DATE; mode = MODE_DATE;
} }
/* continue into the MODE_DATE */ /* continue into the MODE_DATE */
case MODE_DATE: case MODE_DATE:
printf("%c", buf[i]); printf("%c", buf[i]);
if(buf[i] == '\n') { if(buf[i] == '\n') {
mode = MODE_START_DATE; mode = MODE_START_DATE;
} }
break; break;
case MODE_INT: case MODE_INT:
printf("%03d ", buf[i]); printf("%03d ", buf[i]);
if(++index >= ICOLS) { if(++index >= ICOLS) {
index = 0; index = 0;
printf("\n"); printf("\n");
} }
break; break;
case MODE_HEX: case MODE_HEX:
rxbuf[index++] = buf[i]; rxbuf[index++] = buf[i];
if(index >= HCOLS) { if(index >= HCOLS) {
print_hex_line("", rxbuf, index); print_hex_line("", rxbuf, index);
index = 0; index = 0;
printf("\n"); printf("\n");
} }
break; break;
case MODE_SLIP_AUTO: case MODE_SLIP_AUTO:
case MODE_SLIP_HIDE: case MODE_SLIP_HIDE:
if(!flags && (buf[i] != SLIP_END)) { if(!flags && (buf[i] != SLIP_END)) {
/* Not a SLIP packet? */ /* Not a SLIP packet? */
printf("%c", buf[i]); printf("%c", buf[i]);
break; break;
} }
/* continue to slip only mode */ /* continue to slip only mode */
case MODE_SLIP: case MODE_SLIP:
switch(buf[i]) { switch(buf[i]) {
case SLIP_ESC: case SLIP_ESC:
lastc = SLIP_ESC; lastc = SLIP_ESC;
break; break;
case SLIP_END: case SLIP_END:
if(index > 0) { if(index > 0) {
if(flags != 2 && mode != MODE_SLIP_HIDE) { if(flags != 2 && mode != MODE_SLIP_HIDE) {
/* not overflowed: show packet */ /* not overflowed: show packet */
print_hex_line("SLIP: ", rxbuf, print_hex_line("SLIP: ", rxbuf, index > HCOLS ? HCOLS : index);
index > HCOLS ? HCOLS : index); printf("\n");
printf("\n"); }
} lastc = '\0';
lastc = '\0'; index = 0;
index = 0; flags = 0;
flags = 0; } else {
} else { flags = !flags;
flags = !flags; }
} break;
break;
default: default:
if(lastc == SLIP_ESC) { if(lastc == SLIP_ESC) {
lastc = '\0'; lastc = '\0';
/* Previous read byte was an escape byte, so this byte will be /* Previous read byte was an escape byte, so this byte will be
interpreted differently from others. */ interpreted differently from others. */
switch(buf[i]) { switch(buf[i]) {
case SLIP_ESC_END: case SLIP_ESC_END:
buf[i] = SLIP_END; buf[i] = SLIP_END;
break; break;
case SLIP_ESC_ESC: case SLIP_ESC_ESC:
buf[i] = SLIP_ESC; buf[i] = SLIP_ESC;
break; break;
} }
} }
rxbuf[index++] = buf[i]; rxbuf[index++] = buf[i];
if(index >= sizeof(rxbuf)) { if(index >= sizeof(rxbuf)) {
fprintf(stderr, "**** slip overflow\n"); fprintf(stderr, "**** slip overflow\n");
index = 0; index = 0;
flags = 2; flags = 2;
} }
break; break;
} }
break; break;
} }
} }
/* after processing for some output modes */ /* after processing for some output modes */
if(index > 0) { if(index > 0) {
switch(mode) { switch(mode) {
case MODE_HEX: case MODE_HEX:
print_hex_line("", rxbuf, index); print_hex_line("", rxbuf, index);
break; break;
} }
} }
fflush(stdout); fflush(stdout);
} }