X-Git-Url: https://rtime.felk.cvut.cz/gitweb/can-utils.git/blobdiff_plain/03c1bacfdea87e58163269d89f1a202fa4db3dfc..HEAD:/candump.c diff --git a/candump.c b/candump.c index c865bd7..c983b71 100644 --- a/candump.c +++ b/candump.c @@ -43,6 +43,7 @@ #include #include +#include #include #include #include @@ -60,10 +61,15 @@ #include #include +#include #include "terminal.h" #include "lib.h" +#ifndef SIOCSHWTSTAMP +# define SIOCSHWTSTAMP 0x89b0 +#endif + #define MAXSOCK 16 /* max. number of CAN interfaces given on the cmdline */ #define MAXIFNAMES 30 /* size of receive name index to omit ioctls */ #define MAXCOL 6 /* number of different colors for colorized output */ @@ -107,6 +113,7 @@ void print_usage(char *prg) fprintf(stderr, "\nUsage: %s [options] +\n", prg); fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg); fprintf(stderr, "Options: -t (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n"); + fprintf(stderr, " -H (use hardware timestamping)\n"); fprintf(stderr, " -c (increment color mode level)\n"); fprintf(stderr, " -i (binary output - may exceed 80 chars/line)\n"); fprintf(stderr, " -a (enable additional ASCII output)\n"); @@ -130,6 +137,7 @@ void print_usage(char *prg) fprintf(stderr, " : (matches when & mask == can_id & mask)\n"); fprintf(stderr, " ~ (matches when & mask != can_id & mask)\n"); fprintf(stderr, " # (set error frame filter, see include/linux/can/error.h)\n"); + fprintf(stderr, " [j|J] (join the given CAN filters - logical AND semantic)\n"); fprintf(stderr, "\nCAN IDs, masks and data content are given and expected in hexadecimal values.\n"); fprintf(stderr, "When can_id and can_mask are both 8 digits, they are assumed to be 29 bit EFF.\n"); fprintf(stderr, "Without any given filter all data frames are received ('0:0' default filter).\n"); @@ -205,6 +213,7 @@ int main(int argc, char **argv) int bridge = 0; useconds_t bridge_delay = 0; unsigned char timestamp = 0; + int hw_timestamp = 0; unsigned char dropmonitor = 0; unsigned char extra_msg_info = 0; unsigned char silent = SILENT_INI; @@ -217,6 +226,7 @@ int main(int argc, char **argv) int rcvbuf_size = 0; int opt, ret; int currmax, numfilter; + int join_filter; char *ptr, *nptr; struct sockaddr_can addr; char ctrlmsg[CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(sizeof(__u32))]; @@ -239,7 +249,7 @@ int main(int argc, char **argv) last_tv.tv_sec = 0; last_tv.tv_usec = 0; - while ((opt = getopt(argc, argv, "t:ciaSs:b:B:u:ldxLn:r:heT:?")) != -1) { + while ((opt = getopt(argc, argv, "t:ciaSs:b:B:u:ldxLn:r:heT:H?")) != -1) { switch (opt) { case 't': timestamp = optarg[0]; @@ -251,6 +261,10 @@ int main(int argc, char **argv) } break; + case 'H': + hw_timestamp = 1; + break; + case 'c': color++; break; @@ -466,6 +480,7 @@ int main(int argc, char **argv) numfilter = 0; err_mask = 0; + join_filter = 0; while (nptr) { @@ -483,6 +498,8 @@ int main(int argc, char **argv) rfilter[numfilter].can_id |= CAN_INV_FILTER; rfilter[numfilter].can_mask &= ~CAN_ERR_FLAG; numfilter++; + } else if (*ptr == 'j' || *ptr == 'J') { + join_filter = 1; } else if (sscanf(ptr, "#%x", &err_mask) != 1) { fprintf(stderr, "Error in filter option parsing: '%s'\n", ptr); return 1; @@ -493,6 +510,12 @@ int main(int argc, char **argv) setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &err_mask, sizeof(err_mask)); + if (join_filter && setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_JOIN_FILTERS, + &join_filter, sizeof(join_filter)) < 0) { + perror("setsockopt CAN_RAW_JOIN_FILTERS not supported by your Linux Kernel"); + return 1; + } + if (numfilter) setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FILTER, rfilter, numfilter * sizeof(struct can_filter)); @@ -536,13 +559,36 @@ int main(int argc, char **argv) } if (timestamp || log || logfrmt) { + if (hw_timestamp == 0) { + const int timestamp_on = 1; - const int timestamp_on = 1; + if (setsockopt(s[i], SOL_SOCKET, SO_TIMESTAMP, + ×tamp_on, sizeof(timestamp_on)) < 0) { + perror("setsockopt SO_TIMESTAMP"); + return 1; + } + } else { + struct ifreq hwtstamp; + struct hwtstamp_config hwconfig; + + memset(&hwtstamp, 0, sizeof(hwtstamp)); + strncpy(hwtstamp.ifr_name, ifr.ifr_name, sizeof(hwtstamp.ifr_name)); + hwtstamp.ifr_data = (void *)&hwconfig; + memset(&hwconfig, 0, sizeof(hwconfig)); + hwconfig.tx_type = HWTSTAMP_TX_OFF; + hwconfig.rx_filter = HWTSTAMP_FILTER_ALL; + + if (ioctl(s[i], SIOCSHWTSTAMP, &hwtstamp) < 0) { + perror("SIOCSHWTSTAMP"); + return 1; + } - if (setsockopt(s[i], SOL_SOCKET, SO_TIMESTAMP, - ×tamp_on, sizeof(timestamp_on)) < 0) { - perror("setsockopt SO_TIMESTAMP"); - return 1; + const int so_timestamping_flags = SOF_TIMESTAMPING_RAW_HARDWARE; + + if (setsockopt(s[i], SOL_SOCKET, SO_TIMESTAMPING, + &so_timestamping_flags, + sizeof(so_timestamping_flags)) < 0) + perror("setsockopt SO_TIMESTAMPING"); } } @@ -668,17 +714,18 @@ int main(int argc, char **argv) tv = *(struct timeval *)CMSG_DATA(cmsg); else if (cmsg->cmsg_type == SO_RXQ_OVFL) dropcnt[i] = *(__u32 *)CMSG_DATA(cmsg); + else if (cmsg->cmsg_type == SO_TIMESTAMPING) { + struct timespec *ts = (struct timespec *) CMSG_DATA(cmsg); + tv.tv_sec = ts[2].tv_sec; + tv.tv_usec = ts[2].tv_nsec / 1000; + } + } /* check for (unlikely) dropped frames on this specific socket */ if (dropcnt[i] != last_dropcnt[i]) { - __u32 frames; - - if (dropcnt[i] > last_dropcnt[i]) - frames = dropcnt[i] - last_dropcnt[i]; - else - frames = 4294967295U - last_dropcnt[i] + dropcnt[i]; /* 4294967295U == UINT32_MAX */ + __u32 frames = dropcnt[i] - last_dropcnt[i]; if (silent != SILENT_ON) printf("DROPCOUNT: dropped %d CAN frame%s on '%s' socket (total drops %d)\n", @@ -698,18 +745,23 @@ int main(int argc, char **argv) view |= CANLIB_VIEW_INDENT_SFF; if (log) { + char buf[CL_CFSZ]; /* max length */ + /* log CAN frame with absolute timestamp & device */ - fprintf(logfile, "(%010ld.%06ld) ", tv.tv_sec, tv.tv_usec); - fprintf(logfile, "%*s ", max_devname_len, devname[idx]); - /* without separator as logfile use-case is parsing */ - fprint_canframe(logfile, &frame, "\n", 0, maxdlen); + sprint_canframe(buf, &frame, 0, maxdlen); + fprintf(logfile, "(%010ld.%06ld) %*s %s\n", + tv.tv_sec, tv.tv_usec, + max_devname_len, devname[idx], buf); } if (logfrmt) { + char buf[CL_CFSZ]; /* max length */ + /* print CAN frame in log file style to stdout */ - printf("(%010ld.%06ld) ", tv.tv_sec, tv.tv_usec); - printf("%*s ", max_devname_len, devname[idx]); - fprint_canframe(stdout, &frame, "\n", 0, maxdlen); + sprint_canframe(buf, &frame, 0, maxdlen); + printf("(%010ld.%06ld) %*s %s\n", + tv.tv_sec, tv.tv_usec, + max_devname_len, devname[idx], buf); goto out_fflush; /* no other output to stdout */ }