From 016bcdb8a88ba2397523cb009c199be8de9718f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20=27Morty=27=20Str=C3=BCbe?= Date: Fri, 8 May 2015 08:53:56 +0200 Subject: [PATCH 1/6] Fix indentation --- tools/sky/serialdump.c | 419 ++++++++++++++++++++--------------------- 1 file changed, 209 insertions(+), 210 deletions(-) diff --git a/tools/sky/serialdump.c b/tools/sky/serialdump.c index ce6c2ae32..1174dbbec 100644 --- a/tools/sky/serialdump.c +++ b/tools/sky/serialdump.c @@ -15,26 +15,26 @@ #define MODEMDEVICE "/dev/com1" #endif /* linux */ -#define SLIP_END 0300 -#define SLIP_ESC 0333 -#define SLIP_ESC_END 0334 -#define SLIP_ESC_ESC 0335 +#define SLIP_END 0300 +#define SLIP_ESC 0333 +#define SLIP_ESC_END 0334 +#define SLIP_ESC_ESC 0335 -#define CSNA_INIT 0x01 +#define CSNA_INIT 0x01 -#define BUFSIZE 40 -#define HCOLS 20 -#define ICOLS 18 +#define BUFSIZE 40 +#define HCOLS 20 +#define ICOLS 18 -#define MODE_START_DATE 0 -#define MODE_DATE 1 -#define MODE_START_TEXT 2 -#define MODE_TEXT 3 -#define MODE_INT 4 -#define MODE_HEX 5 -#define MODE_SLIP_AUTO 6 -#define MODE_SLIP 7 -#define MODE_SLIP_HIDE 8 +#define MODE_START_DATE 0 +#define MODE_DATE 1 +#define MODE_START_TEXT 2 +#define MODE_TEXT 3 +#define MODE_INT 4 +#define MODE_HEX 5 +#define MODE_SLIP_AUTO 6 +#define MODE_SLIP 7 +#define MODE_SLIP_HIDE 8 static unsigned char rxbuf[2048]; @@ -80,7 +80,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; fd_set mask, smask; @@ -95,100 +96,100 @@ int main(int argc, char **argv) unsigned char lastc = '\0'; int index = 1; - while (index < argc) { - if (argv[index][0] == '-') { + while(index < argc) { + if(argv[index][0] == '-') { switch(argv[index][1]) { - case 'b': - /* set speed */ - if (strcmp(&argv[index][2], "38400") == 0) { - speed = B38400; - speedname = "38400"; - } else if (strcmp(&argv[index][2], "19200") == 0) { - speed = B19200; - speedname = "19200"; - } else if (strcmp(&argv[index][2], "57600") == 0) { - speed = B57600; - speedname = "57600"; - } else if (strcmp(&argv[index][2], "115200") == 0) { - speed = B115200; - speedname = "115200"; - } else { - fprintf(stderr, "unsupported speed: %s\n", &argv[index][2]); - return usage(1); - } - break; - case 'x': - mode = MODE_HEX; - break; - case 'i': - mode = MODE_INT; - break; - case 's': - switch(argv[index][2]) { - case 'n': - mode = MODE_SLIP_HIDE; - break; - case 'o': - mode = MODE_SLIP; - break; - default: - mode = MODE_SLIP_AUTO; - break; - } - break; - case 'T': - if(strlen(&argv[index][2]) == 0) { - timeformat = "%Y-%m-%d %H:%M:%S"; - } else { - timeformat = &argv[index][2]; - } - mode = MODE_START_DATE; - break; - case 'h': - return usage(0); - default: - fprintf(stderr, "unknown option '%c'\n", argv[index][1]); - return usage(1); + case 'b': + /* set speed */ + if(strcmp(&argv[index][2], "38400") == 0) { + speed = B38400; + speedname = "38400"; + } else if(strcmp(&argv[index][2], "19200") == 0) { + speed = B19200; + speedname = "19200"; + } else if(strcmp(&argv[index][2], "57600") == 0) { + speed = B57600; + speedname = "57600"; + } else if(strcmp(&argv[index][2], "115200") == 0) { + speed = B115200; + speedname = "115200"; + } else { + fprintf(stderr, "unsupported speed: %s\n", &argv[index][2]); + return usage(1); + } + break; + case 'x': + mode = MODE_HEX; + break; + case 'i': + mode = MODE_INT; + break; + case 's': + switch(argv[index][2]) { + case 'n': + mode = MODE_SLIP_HIDE; + break; + case 'o': + mode = MODE_SLIP; + break; + default: + mode = MODE_SLIP_AUTO; + break; + } + break; + case 'T': + if(strlen(&argv[index][2]) == 0) { + timeformat = "%Y-%m-%d %H:%M:%S"; + } else { + timeformat = &argv[index][2]; + } + mode = MODE_START_DATE; + break; + case 'h': + return usage(0); + default: + fprintf(stderr, "unknown option '%c'\n", argv[index][1]); + return usage(1); } index++; } else { device = argv[index++]; - if (index < argc) { - fprintf(stderr, "too many arguments\n"); - return usage(1); + if(index < argc) { + fprintf(stderr, "too many arguments\n"); + return usage(1); } } } fprintf(stderr, "connecting to %s (%s)", device, speedname); #ifndef __APPLE__ - 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); #else fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_SYNC ); #endif - if (fd <0) { + if(fd < 0) { fprintf(stderr, "\n"); perror(device); exit(-1); } fprintf(stderr, " [OK]\n"); - if (fcntl(fd, F_SETFL, 0) < 0) { + if(fcntl(fd, F_SETFL, 0) < 0) { perror("could not set fcntl"); exit(-1); } - if (tcgetattr(fd, &options) < 0) { + if(tcgetattr(fd, &options) < 0) { perror("could not get options"); exit(-1); } -/* fprintf(stderr, "serial options set\n"); */ + /* fprintf(stderr, "serial options set\n"); */ cfsetispeed(&options, speed); cfsetospeed(&options, speed); /* Enable the receiver and set local mode */ options.c_cflag |= (CLOCAL | CREAD); /* 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 */ options.c_cflag |= CS8; @@ -197,30 +198,29 @@ int main(int argc, char **argv) /* Raw output */ options.c_oflag &= ~OPOST; - if (tcsetattr(fd, TCSANOW, &options) < 0) { + if(tcsetattr(fd, TCSANOW, &options) < 0) { perror("could not set options"); exit(-1); } /* Make read() return immediately */ -/* if (fcntl(fd, F_SETFL, FNDELAY) < 0) { */ -/* perror("\ncould not set fcntl"); */ -/* exit(-1); */ -/* } */ + /* if (fcntl(fd, F_SETFL, FNDELAY) < 0) { */ + /* perror("\ncould not set fcntl"); */ + /* exit(-1); */ + /* } */ FD_ZERO(&mask); FD_SET(fd, &mask); FD_SET(fileno(stdin), &mask); index = 0; - for (;;) { + for(;;) { smask = mask; - nfound = select(FD_SETSIZE, &smask, (fd_set *) 0, (fd_set *) 0, - (struct timeval *) 0); + nfound = select(FD_SETSIZE, &smask, (fd_set *) 0, (fd_set *) 0, (struct timeval *) 0); if(nfound < 0) { - if (errno == EINTR) { - fprintf(stderr, "interrupted system call\n"); - continue; + if(errno == EINTR) { + fprintf(stderr, "interrupted system call\n"); + continue; } /* something is very wrong! */ perror("select"); @@ -230,143 +230,142 @@ int main(int argc, char **argv) if(FD_ISSET(fileno(stdin), &smask)) { /* data from standard in */ int n = read(fileno(stdin), buf, sizeof(buf)); - if (n < 0) { - perror("could not read"); - exit(-1); - } else if (n > 0) { - /* because commands might need parameters, lines needs to be - separated which means the terminating LF must be sent */ -/* while(n > 0 && buf[n - 1] < 32) { */ -/* n--; */ -/* } */ - if(n > 0) { - int i; - /* fprintf(stderr, "SEND %d bytes\n", n);*/ - /* write slowly */ - for (i = 0; i < n; i++) { - if (write(fd, &buf[i], 1) <= 0) { - perror("write"); - exit(1); - } else { - fflush(NULL); - usleep(6000); - } - } - } + if(n < 0) { + perror("could not read"); + exit(-1); + } else if(n > 0) { + /* because commands might need parameters, lines needs to be + separated which means the terminating LF must be sent */ + /* while(n > 0 && buf[n - 1] < 32) { */ + /* n--; */ + /* } */ + if(n > 0) { + int i; + /* fprintf(stderr, "SEND %d bytes\n", n);*/ + /* write slowly */ + for(i = 0; i < n; i++) { + if(write(fd, &buf[i], 1) <= 0) { + perror("write"); + exit(1); + } else { + fflush(NULL); + usleep(6000); + } + } + } } else { - /* End of input, exit. */ - exit(0); + /* End of input, exit. */ + exit(0); } } if(FD_ISSET(fd, &smask)) { int i, j, n = read(fd, buf, sizeof(buf)); - if (n < 0) { - perror("could not read"); - exit(-1); + if(n < 0) { + perror("could not read"); + exit(-1); } for(i = 0; i < n; i++) { - switch(mode) { - case MODE_START_TEXT: - case MODE_TEXT: - printf("%c", buf[i]); - break; - case MODE_START_DATE: { - time_t t; - t = time(&t); - strftime(outbuf, HCOLS, timeformat, localtime(&t)); - printf("%s|", outbuf); - mode = MODE_DATE; - } - /* continue into the MODE_DATE */ - case MODE_DATE: - printf("%c", buf[i]); - if(buf[i] == '\n') { - mode = MODE_START_DATE; - } - break; - case MODE_INT: - printf("%03d ", buf[i]); - if(++index >= ICOLS) { - index = 0; - printf("\n"); - } - break; - case MODE_HEX: - rxbuf[index++] = buf[i]; - if(index >= HCOLS) { - print_hex_line("", rxbuf, index); - index = 0; - printf("\n"); - } - break; + switch(mode) { + case MODE_START_TEXT: + case MODE_TEXT: + printf("%c", buf[i]); + break; + case MODE_START_DATE: { + time_t t; + t = time(&t); + strftime(outbuf, HCOLS, timeformat, localtime(&t)); + printf("%s|", outbuf); + mode = MODE_DATE; + } + /* continue into the MODE_DATE */ + case MODE_DATE: + printf("%c", buf[i]); + if(buf[i] == '\n') { + mode = MODE_START_DATE; + } + break; + case MODE_INT: + printf("%03d ", buf[i]); + if(++index >= ICOLS) { + index = 0; + printf("\n"); + } + break; + case MODE_HEX: + rxbuf[index++] = buf[i]; + if(index >= HCOLS) { + print_hex_line("", rxbuf, index); + index = 0; + printf("\n"); + } + break; - case MODE_SLIP_AUTO: - case MODE_SLIP_HIDE: - if(!flags && (buf[i] != SLIP_END)) { - /* Not a SLIP packet? */ - printf("%c", buf[i]); - break; - } - /* continue to slip only mode */ - case MODE_SLIP: - switch(buf[i]) { - case SLIP_ESC: - lastc = SLIP_ESC; - break; + case MODE_SLIP_AUTO: + case MODE_SLIP_HIDE: + if(!flags && (buf[i] != SLIP_END)) { + /* Not a SLIP packet? */ + printf("%c", buf[i]); + break; + } + /* continue to slip only mode */ + case MODE_SLIP: + switch(buf[i]) { + case SLIP_ESC: + lastc = SLIP_ESC; + break; - case SLIP_END: - if(index > 0) { - if(flags != 2 && mode != MODE_SLIP_HIDE) { - /* not overflowed: show packet */ - print_hex_line("SLIP: ", rxbuf, - index > HCOLS ? HCOLS : index); - printf("\n"); - } - lastc = '\0'; - index = 0; - flags = 0; - } else { - flags = !flags; - } - break; + case SLIP_END: + if(index > 0) { + if(flags != 2 && mode != MODE_SLIP_HIDE) { + /* not overflowed: show packet */ + print_hex_line("SLIP: ", rxbuf, index > HCOLS ? HCOLS : index); + printf("\n"); + } + lastc = '\0'; + index = 0; + flags = 0; + } else { + flags = !flags; + } + break; - default: - if(lastc == SLIP_ESC) { - lastc = '\0'; + default: + if(lastc == SLIP_ESC) { + lastc = '\0'; - /* Previous read byte was an escape byte, so this byte will be - interpreted differently from others. */ - switch(buf[i]) { - case SLIP_ESC_END: - buf[i] = SLIP_END; - break; - case SLIP_ESC_ESC: - buf[i] = SLIP_ESC; - break; - } - } + /* Previous read byte was an escape byte, so this byte will be + interpreted differently from others. */ + switch(buf[i]) { + case SLIP_ESC_END: + buf[i] = SLIP_END; + break; + case SLIP_ESC_ESC: + buf[i] = SLIP_ESC; + break; + } + } - rxbuf[index++] = buf[i]; - if(index >= sizeof(rxbuf)) { - fprintf(stderr, "**** slip overflow\n"); - index = 0; - flags = 2; - } - break; - } - break; - } + rxbuf[index++] = buf[i]; + if(index >= sizeof(rxbuf)) { + fprintf(stderr, "**** slip overflow\n"); + index = 0; + flags = 2; + } + break; + } + break; + } } /* after processing for some output modes */ if(index > 0) { - switch(mode) { - case MODE_HEX: - print_hex_line("", rxbuf, index); - break; - } + switch(mode) { + case MODE_HEX: + print_hex_line("", rxbuf, index); + break; + } } fflush(stdout); } From d26afef966dc0ec0cfe53d639c01b5bfbc8c61ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20=27Morty=27=20Str=C3=BCbe?= Date: Tue, 5 May 2015 18:14:35 +0200 Subject: [PATCH 2/6] Fix serialdump.c _GNU_SOURCE is needed for O_DIRECT time.h is needed for strftime --- tools/sky/serialdump.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/sky/serialdump.c b/tools/sky/serialdump.c index 1174dbbec..4a0573b9d 100644 --- a/tools/sky/serialdump.c +++ b/tools/sky/serialdump.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include #include @@ -6,6 +7,7 @@ #include #include #include +#include #define BAUDRATE B57600 #define BAUDRATE_S "57600" From 425c58e79dca67d380048b08c1b884543d6887cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20=27Morty=27=20Str=C3=BCbe?= Date: Fri, 8 May 2015 08:55:31 +0200 Subject: [PATCH 3/6] Set default speed to 115200 --- tools/sky/serialdump.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/sky/serialdump.c b/tools/sky/serialdump.c index 4a0573b9d..447999026 100644 --- a/tools/sky/serialdump.c +++ b/tools/sky/serialdump.c @@ -9,8 +9,8 @@ #include #include -#define BAUDRATE B57600 -#define BAUDRATE_S "57600" +#define BAUDRATE B115200 +#define BAUDRATE_S "115200" #ifdef linux #define MODEMDEVICE "/dev/ttyS0" #else From 1e359d232451f19d668359ff5da79e3db021e99d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20=27Morty=27=20Str=C3=BCbe?= Date: Fri, 8 May 2015 09:14:40 +0200 Subject: [PATCH 4/6] Improve O_SYNC logic --- tools/sky/serialdump.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/sky/serialdump.c b/tools/sky/serialdump.c index 447999026..d0e7fac3c 100644 --- a/tools/sky/serialdump.c +++ b/tools/sky/serialdump.c @@ -164,8 +164,11 @@ main(int argc, char **argv) } 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); + if(fd < 0 && errno == EINVAL){ // O_SYNC not supported (e.g. raspberian) + fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_DIRECT); + } #else fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_SYNC ); #endif From 16f7c2448cc1d2eb5c90e90169169636a9d8fff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20=27Morty=27=20Str=C3=BCbe?= Date: Fri, 8 May 2015 09:15:21 +0200 Subject: [PATCH 5/6] Improve error message --- tools/sky/serialdump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/sky/serialdump.c b/tools/sky/serialdump.c index d0e7fac3c..e3e47092b 100644 --- a/tools/sky/serialdump.c +++ b/tools/sky/serialdump.c @@ -174,7 +174,7 @@ main(int argc, char **argv) #endif if(fd < 0) { fprintf(stderr, "\n"); - perror(device); + perror("open"); exit(-1); } fprintf(stderr, " [OK]\n"); From 23d625058434dafd545f1c4a3171804b879ccbc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20=27Morty=27=20Str=C3=BCbe?= Date: Fri, 8 May 2015 09:21:19 +0200 Subject: [PATCH 6/6] Turn on optimization --- tools/sky/Makefile | 2 +- tools/sky/serialdump-linux | Bin 14922 -> 14748 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/sky/Makefile b/tools/sky/Makefile index 0b1fa08db..be3caa44b 100644 --- a/tools/sky/Makefile +++ b/tools/sky/Makefile @@ -22,4 +22,4 @@ endif all: $(SERIALDUMP) $(SERIALDUMP): serialdump.c - $(CC) -o $@ $< + $(CC) -O2 -o $@ $< diff --git a/tools/sky/serialdump-linux b/tools/sky/serialdump-linux index 8c7af779d6833ab75857ae8d2a59688e0d68cfab..8bb8192c282daa79e093d45bfdc0da9fdf59bb5b 100755 GIT binary patch literal 14748 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 B*9rgt literal 14922 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 z�(x%ft#10c8|sE{H1IbbWmTTSY~%382|{>N*ybfRG)l$Ov~UsN`W5Vuabvz{&(F zgP1uPA#Q<&VR1%&QHcU5dqM&VLgEZAMAZN0%sAT2+%SOP(lLLji5D@p!JlX5&)(d zBnM)HvL(1oXMnDEWQ42@1Id9fXxOjm!Bz2%t?13oi`cIhA z?ND_fe=tmA;Q%e*>;N^aL54u>1u^@P)OE~c;pmWrwU|J%2=+{qTaIKNXtj@k0>TWCnV>KM(QBY#3^EVYCKpkFtl0&{FGwDw z4iq0-k<0_Fp}T{{JdoO5Na{d+j0Xw~44}nXAhSRiqy~gRYc65_@L0&g;h~7SCKsdz zr2ZtR2?R~kpt*q%MFs{1kb^*yps{BteGY0bl*<58rv|bBDga|%M^o3J#J~WmZlKD* z>vTbE(ArX%9uS{HnSntS#DHR$+&47ybd?zxw84o2q7bHz2~^iZgurBkDgy(k*$U<$ znIV9t?wl$E!)}-%Na|#u>Oc$aKxTBRGcfE2F`yWv1%yHEPf*-Kg&90F7#P$+5>Npc z6GS69o8f>S1H%P21_n_38?^2h6d$1S1(e5;&6{A#z_1G>iDn*@i$a0QOOOC$B|D^C zgzzCYgUUY$A7TTjoP+Qo7J$k#2p^IN56b-v450D}!UvVS3=E)h2*QUX7*Kfw z;e&j^zyK;&Abe0ynSlXRen9x3k_gi0f$%{+ZUzQWc>v*qdfp5S;Cv5Gn~;J8l)oYJ zptVlWb@E_&P{=VbfbuIu9uzAK44`}o;e&cikahDAKBPtglo5@_cOB*w(R!_Wd^Kru)jR1Sk?<3K`;3<3~ zgYp@eKK|c^#y^S1zr~11uZ&Eh3?Ij( z;0xj-t-%ig@saj4q(S+h@(Yx^DxrMP-T)B48_EZjZ6N+4C?B+<4aDEV#K7PK3J(Sb z20MEL}APdYOLg9K=4F*v+<7|NL$ z7($@#7hw4KznPhV0kr1WnH#i6gNFguRsq#>AoG?oGcdr)69on_h7C~rVE#G8j41zv z7b3EN(*ippgrZd9R^-SbYA5@?m={xLHu$Cj{~+0|R*E0;FG)g@FOotptUk z5EBoB0}BH~!%9f{2l>a91+r!zqzx2aVJr*`pivMApN}Dx1>qk71~G;rkOasuXq%x8 z%7^XIm<{E_+`Age2WbI~fiff}W$J=EO2G_Ry6o^_B~Z^tFPQ;EfjT~V$rOyhfTm)R zc7cF8-NhxPX=!@N4Ds>KA^t(}KAyoL@$n4t@h&JlFK4(^a(-?>PHIVNik^vynK45F zh%#b`k59>uPtVCuO3aA|cfjHkODh<_9kck9(%jrim<6tWE(r5s9Je4xU)OjT4`dmP zjW8A5y91jF=_x}gjNL@YhJXeN zpo+l>B@I~;;%)F631nf&1}bC`(Do!`K4@