Add option to read hardware timestamps.

pull/59/head
Fabián Inostroza 2017-12-02 03:33:43 -03:00
parent 5b518a0a5f
commit fbebc61881
1 changed files with 36 additions and 9 deletions

View File

@ -58,6 +58,7 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <net/if.h> #include <net/if.h>
#include <linux/net_tstamp.h>
#include <linux/can.h> #include <linux/can.h>
#include <linux/can/raw.h> #include <linux/can/raw.h>
@ -108,6 +109,7 @@ void print_usage(char *prg)
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg); fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg); fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg);
fprintf(stderr, "Options: -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n"); fprintf(stderr, "Options: -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n");
fprintf(stderr, " -H (Read hardware timestamps)\n");
fprintf(stderr, " -c (increment color mode level)\n"); fprintf(stderr, " -c (increment color mode level)\n");
fprintf(stderr, " -i (binary output - may exceed 80 chars/line)\n"); fprintf(stderr, " -i (binary output - may exceed 80 chars/line)\n");
fprintf(stderr, " -a (enable additional ASCII output)\n"); fprintf(stderr, " -a (enable additional ASCII output)\n");
@ -208,6 +210,7 @@ int main(int argc, char **argv)
int bridge = 0; int bridge = 0;
useconds_t bridge_delay = 0; useconds_t bridge_delay = 0;
unsigned char timestamp = 0; unsigned char timestamp = 0;
unsigned char hwtimestamp = 0;
unsigned char down_causes_exit = 1; unsigned char down_causes_exit = 1;
unsigned char dropmonitor = 0; unsigned char dropmonitor = 0;
unsigned char extra_msg_info = 0; unsigned char extra_msg_info = 0;
@ -224,7 +227,10 @@ int main(int argc, char **argv)
int join_filter; int join_filter;
char *ptr, *nptr; char *ptr, *nptr;
struct sockaddr_can addr; struct sockaddr_can addr;
char ctrlmsg[CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(sizeof(__u32))]; struct {
struct cmsghdr cm;
char control[512];
} ctrlmsg;
struct iovec iov; struct iovec iov;
struct msghdr msg; struct msghdr msg;
struct cmsghdr *cmsg; struct cmsghdr *cmsg;
@ -244,7 +250,7 @@ int main(int argc, char **argv)
last_tv.tv_sec = 0; last_tv.tv_sec = 0;
last_tv.tv_usec = 0; last_tv.tv_usec = 0;
while ((opt = getopt(argc, argv, "t:ciaSs:b:B:u:lDdxLn:r:heT:?")) != -1) { while ((opt = getopt(argc, argv, "t:HciaSs:b:B:u:lDdxLn:r:heT:?")) != -1) {
switch (opt) { switch (opt) {
case 't': case 't':
timestamp = optarg[0]; timestamp = optarg[0];
@ -256,6 +262,10 @@ int main(int argc, char **argv)
} }
break; break;
case 'H':
hwtimestamp = 1;
break;
case 'c': case 'c':
color++; color++;
break; break;
@ -555,12 +565,21 @@ int main(int argc, char **argv)
if (timestamp || log || logfrmt) { if (timestamp || log || logfrmt) {
const int timestamp_on = 1; int timestamping_flags = 1;
if (hwtimestamp) {
if (setsockopt(s[i], SOL_SOCKET, SO_TIMESTAMP, timestamping_flags = SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_RX_SOFTWARE | \
&timestamp_on, sizeof(timestamp_on)) < 0) { SOF_TIMESTAMPING_RAW_HARDWARE | SOF_TIMESTAMPING_SYS_HARDWARE;
perror("setsockopt SO_TIMESTAMP"); if (setsockopt(s[i], SOL_SOCKET, SO_TIMESTAMPING,
return 1; &timestamping_flags, sizeof(timestamping_flags)) < 0) {
perror("setsockopt SO_TIMESTAMPING");
return 1;
}
} else {
if (setsockopt(s[i], SOL_SOCKET, SO_TIMESTAMP,
&timestamping_flags, sizeof(timestamping_flags)) < 0) {
perror("setsockopt SO_TIMESTAMP");
return 1;
}
} }
} }
@ -688,8 +707,16 @@ int main(int argc, char **argv)
for (cmsg = CMSG_FIRSTHDR(&msg); for (cmsg = CMSG_FIRSTHDR(&msg);
cmsg && (cmsg->cmsg_level == SOL_SOCKET); cmsg && (cmsg->cmsg_level == SOL_SOCKET);
cmsg = CMSG_NXTHDR(&msg,cmsg)) { cmsg = CMSG_NXTHDR(&msg,cmsg)) {
if (cmsg->cmsg_type == SO_TIMESTAMP) if (cmsg->cmsg_type == SO_TIMESTAMP) {
memcpy(&tv, CMSG_DATA(cmsg), sizeof(tv)); memcpy(&tv, CMSG_DATA(cmsg), sizeof(tv));
} else if (cmsg->cmsg_type == SO_TIMESTAMPING) {
struct timespec *stamp = (struct timespec *)CMSG_DATA(cmsg);
stamp += 2;
tv.tv_sec = stamp->tv_sec;
tv.tv_usec = stamp->tv_nsec/1000;
}
else if (cmsg->cmsg_type == SO_RXQ_OVFL) else if (cmsg->cmsg_type == SO_RXQ_OVFL)
memcpy(&dropcnt[i], CMSG_DATA(cmsg), sizeof(__u32)); memcpy(&dropcnt[i], CMSG_DATA(cmsg), sizeof(__u32));
} }