X-Git-Url: http://rtime.felk.cvut.cz/gitweb/sojka/can-utils.git/blobdiff_plain/adbe6f9beefef2f3e01225146bd40a4f487b43d3..HEAD:/canplayer.c diff --git a/canplayer.c b/canplayer.c index f1d6d7e..f74668e 100644 --- a/canplayer.c +++ b/canplayer.c @@ -1,7 +1,3 @@ -/* - * $Id$ - */ - /* * canplayer.c - replay a compact CAN frame logfile to CAN devices * @@ -41,7 +37,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * - * Send feedback to + * Send feedback to * */ @@ -53,6 +49,7 @@ #include #include +#include #include #include #include @@ -60,10 +57,12 @@ #include "lib.h" -#define DEFAULT_GAP 1 /* ms */ -#define DEFAULT_LOOPS 1 /* only one replay */ -#define CHANNELS 20 /* anyone using more than 20 CAN interfaces at a time? */ -#define BUFSZ 100 /* for one line in the logfile */ +#define DEFAULT_GAP 1 /* ms */ +#define DEFAULT_LOOPS 1 /* only one replay */ +#define CHANNELS 20 /* anyone using more than 20 CAN interfaces at a time? */ +#define COMMENTSZ 200 +#define BUFSZ (sizeof("(1345212884.318850)") + IFNAMSIZ + 4 + CL_CFSZ + COMMENTSZ) /* for one line in the logfile */ +#define STDOUTIDX 65536 /* interface index for printing on stdout - bigger than max uint16 */ struct assignment { char txif[IFNAMSIZ]; @@ -71,6 +70,7 @@ struct assignment { char rxif[IFNAMSIZ]; }; static struct assignment asgn[CHANNELS]; +const int canfd_on = 1; extern int optind, opterr, optopt; @@ -96,8 +96,12 @@ void print_usage(char *prg) "=\n"); fprintf(stderr, "e.g. vcan2=can0 ( send frames received from can0 on " "vcan2 )\n"); + fprintf(stderr, "extra hook: stdout=can0 ( print logfile line marked with can0 on " + "stdout )\n"); fprintf(stderr, "No assignments => send frames to the interface(s) they " "had been received from.\n\n"); + fprintf(stderr, "Lines in the logfile not beginning with '(' (start of " + "timestamp) are ignored.\n\n"); } /* copied from /usr/src/linux/include/linux/time.h ... @@ -208,13 +212,16 @@ int add_assignment(char *mode, int socket, char *txname, char *rxname, } strcpy(asgn[i].rxif, rxname); - strcpy(ifr.ifr_name, txname); - if (ioctl(socket, SIOCGIFINDEX, &ifr) < 0) { - perror("SIOCGIFINDEX"); - fprintf(stderr, "write-if interface name '%s' is wrong!\n", txname); - return 1; - } - asgn[i].txifidx = ifr.ifr_ifindex; + if (strcmp(txname, "stdout")) { + strcpy(ifr.ifr_name, txname); + if (ioctl(socket, SIOCGIFINDEX, &ifr) < 0) { + perror("SIOCGIFINDEX"); + fprintf(stderr, "write-if interface name '%s' is wrong!\n", txname); + return 1; + } + asgn[i].txifidx = ifr.ifr_ifindex; + } else + asgn[i].txifidx = STDOUTIDX; if (verbose > 1) /* use -v -v to see this */ printf("added %s assignment: log-if=%s write-if=%s write-if-idx=%d\n", @@ -227,7 +234,7 @@ int main(int argc, char **argv) { static char buf[BUFSZ], device[BUFSZ], ascframe[BUFSZ]; struct sockaddr_can addr; - static struct can_frame frame; + static struct canfd_frame frame; static struct timeval today_tv, log_tv, last_log_tv, diff_tv; struct timespec sleep_ts; int s; /* CAN_RAW socket */ @@ -240,9 +247,10 @@ int main(int argc, char **argv) static int loops = DEFAULT_LOOPS; int assignments; /* assignments defined on the commandline */ int txidx; /* sendto() interface index */ - int eof, nbytes, i, j; + int eof, txmtu, i, j; + char *fret; - while ((opt = getopt(argc, argv, "I:l:tg:s:xv")) != -1) { + while ((opt = getopt(argc, argv, "I:l:tg:s:xv?")) != -1) { switch (opt) { case 'I': infile = fopen(optarg, "r"); @@ -286,6 +294,7 @@ int main(int argc, char **argv) verbose++; break; + case '?': default: print_usage(basename(argv[0])); return 1; @@ -300,11 +309,12 @@ int main(int argc, char **argv) loops = 1; } - if (verbose > 1) /* use -v -v to see this */ + if (verbose > 1) { /* use -v -v to see this */ if (infinite_loops) printf("infinite_loops\n"); else printf("%d loops\n", loops); + } sleep_ts.tv_sec = gap / 1000; sleep_ts.tv_nsec = (gap % 1000) * 1000000; @@ -321,6 +331,9 @@ int main(int argc, char **argv) /* disable unneeded default receive filter on this RAW socket */ setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0); + /* try to switch the socket into CAN FD mode */ + setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &canfd_on, sizeof(canfd_on)); + if (loopback_disable) { int loopback = 0; @@ -346,7 +359,7 @@ int main(int argc, char **argv) if (buf[j] == '=') break; } - if (buf[j] != '=') { + if ((j == BUFSZ) || (buf[j] != '=')) { fprintf(stderr, "'=' missing in assignment!\n"); print_usage(basename(argv[0])); return 1; @@ -365,14 +378,24 @@ int main(int argc, char **argv) if (verbose > 1) /* use -v -v to see this */ printf (">>>>>>>>> start reading file. remaining loops = %d\n", loops); - if (!fgets(buf, BUFSZ-1, infile)) /* read first frame from logfile */ + /* read first non-comment frame from logfile */ + while ((fret = fgets(buf, BUFSZ-1, infile)) != NULL && buf[0] != '(') { + if (strlen(buf) >= BUFSZ-2) { + fprintf(stderr, "comment line too long for input buffer\n"); + return 1; + } + } + + if (!fret) goto out; /* nothing to read */ eof = 0; if (sscanf(buf, "(%ld.%ld) %s %s", &log_tv.tv_sec, &log_tv.tv_usec, - device, ascframe) != 4) + device, ascframe) != 4) { + fprintf(stderr, "incorrect line format in logfile\n"); return 1; + } if (use_timestamps) { /* throttle sending due to logfile timestamps */ @@ -403,9 +426,15 @@ int main(int argc, char **argv) txidx = get_txidx(device); } - if (txidx) { /* only send to valid CAN devices */ + if (txidx == STDOUTIDX) { /* hook to print logfile lines on stdout */ - if (parse_canframe(ascframe, &frame)) { + printf("%s", buf); /* print the line AS-IS without extra \n */ + fflush(stdout); + + } else if (txidx > 0) { /* only send to valid CAN devices */ + + txmtu = parse_canframe(ascframe, &frame); + if (!txmtu) { fprintf(stderr, "wrong CAN frame format: '%s'!", ascframe); return 1; } @@ -413,29 +442,39 @@ int main(int argc, char **argv) addr.can_family = AF_CAN; addr.can_ifindex = txidx; /* send via this interface */ - nbytes = sendto(s, &frame, sizeof(struct can_frame), 0, - (struct sockaddr*)&addr, sizeof(addr)); - - if (nbytes != sizeof(struct can_frame)) { + if (sendto(s, &frame, txmtu, 0, (struct sockaddr*)&addr, sizeof(addr)) != txmtu) { perror("sendto"); return 1; } if (verbose) { printf("%s (%s) ", get_txname(device), device); - fprint_long_canframe(stdout, &frame, "\n", 1); + + if (txmtu == CAN_MTU) + fprint_long_canframe(stdout, &frame, "\n", CANLIB_VIEW_INDENT_SFF, CAN_MAX_DLEN); + else + fprint_long_canframe(stdout, &frame, "\n", CANLIB_VIEW_INDENT_SFF, CANFD_MAX_DLEN); + } + } + + /* read next non-comment frame from logfile */ + while ((fret = fgets(buf, BUFSZ-1, infile)) != NULL && buf[0] != '(') { + if (strlen(buf) >= BUFSZ-2) { + fprintf(stderr, "comment line too long for input buffer\n"); + return 1; } } - /* read next frame from logfile */ - if (!fgets(buf, BUFSZ-1, infile)) { + if (!fret) { eof = 1; /* this file is completely processed */ break; } if (sscanf(buf, "(%ld.%ld) %s %s", &log_tv.tv_sec, &log_tv.tv_usec, - device, ascframe) != 4) + device, ascframe) != 4) { + fprintf(stderr, "incorrect line format in logfile\n"); return 1; + } if (use_timestamps) { gettimeofday(&today_tv, NULL);