Skip to content

Commit 277048e

Browse files
committed
RealCAN implementation
Replay pre-recorded CAN Bus dumps respecting the original relative timestamps. Fix code style Conform to codebase style as per maintainer's suggestions. Refactor code logic according to suggestions for PR #521
1 parent d05810f commit 277048e

1 file changed

Lines changed: 49 additions & 4 deletions

File tree

canplayer.c

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include <string.h>
4949
#include <time.h>
5050
#include <unistd.h>
51+
#include <stdbool.h>
5152

5253
#include <linux/can.h>
5354
#include <linux/can/raw.h>
@@ -89,6 +90,12 @@ const int canfx_on = 1;
8990

9091
extern int optind, opterr, optopt;
9192

93+
struct sleep {
94+
struct timeval *sleep_vector;
95+
size_t idx;
96+
size_t size;
97+
};
98+
9299
static void print_usage(char *prg)
93100
{
94101
fprintf(stderr, "%s - replay a compact CAN frame logfile to CAN devices.\n", prg);
@@ -117,6 +124,8 @@ static void print_usage(char *prg)
117124
"loopback of sent CAN frames)\n");
118125
fprintf(stderr, " -v (verbose: print "
119126
"sent CAN frames)\n");
127+
fprintf(stderr, " -r (real-time: send "
128+
"CAN frames in real-time)\n");
120129
fprintf(stderr, " -h (show "
121130
"this help message)\n\n");
122131
fprintf(stderr, "Interface assignment:\n");
@@ -280,8 +289,11 @@ int main(int argc, char **argv)
280289
int eof, txmtu, i, j;
281290
char *fret;
282291
unsigned long long sec, usec;
292+
bool gap_from_file = false;
293+
struct sleep timestamps;
294+
struct timeval send_time, act_time, init_trace, init_time;
283295

284-
while ((opt = getopt(argc, argv, "I:l:tin:g:s:xvh")) != -1) {
296+
while ((opt = getopt(argc, argv, "I:l:tin:g:s:xvrh")) != -1) {
285297
switch (opt) {
286298
case 'I':
287299
infile = fopen(optarg, "r");
@@ -336,6 +348,17 @@ int main(int argc, char **argv)
336348
verbose++;
337349
break;
338350

351+
case 'r':
352+
if (isatty(fileno(infile))) {
353+
fprintf(stderr, "Specify an input file for option -r !\n");
354+
exit(EXIT_FAILURE);
355+
}
356+
gap_from_file = true; /* using time delta from file */
357+
init_trace.tv_sec = 0;
358+
init_trace.tv_usec = 0;
359+
timestamps.idx = 0; /*to avoid warning accessing idx variable*/
360+
break;
361+
339362
case 'h':
340363
print_usage(basename(argv[0]));
341364
exit(EXIT_SUCCESS);
@@ -368,8 +391,10 @@ int main(int argc, char **argv)
368391
printf("interactive mode: press ENTER to process next CAN frame ...\n");
369392
}
370393

371-
sleep_ts.tv_sec = gap / 1000;
372-
sleep_ts.tv_nsec = (gap % 1000) * 1000000;
394+
if (!gap_from_file) {
395+
sleep_ts.tv_sec = gap / 1000;
396+
sleep_ts.tv_nsec = (gap % 1000) * 1000000;
397+
}
373398

374399
/* open socket */
375400
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
@@ -548,6 +573,26 @@ int main(int argc, char **argv)
548573
log_tv.tv_sec = sec;
549574
log_tv.tv_usec = usec;
550575

576+
if (gap_from_file){
577+
if (timestamps.idx == 0){
578+
gettimeofday(&init_time, NULL);
579+
if (log_tv.tv_sec > 0 || log_tv.tv_usec > 0)
580+
init_trace = log_tv;
581+
}
582+
timersub(&log_tv, &init_trace, &send_time);
583+
584+
if (timestamps.idx > 0){
585+
gettimeofday(&act_time, NULL);
586+
timersub(&act_time, &init_time, &act_time);
587+
588+
while (timercmp(&act_time, &send_time, <)){
589+
gettimeofday(&act_time, NULL);
590+
timersub(&act_time, &init_time, &act_time);
591+
}
592+
}
593+
timestamps.idx++;
594+
}
595+
551596
/*
552597
* ensure the fractions of seconds are 6 decimal places long to catch
553598
* 3rd party or handcrafted logfiles that treat the timestamp as float
@@ -570,7 +615,7 @@ int main(int argc, char **argv)
570615

571616
} /* while frames_to_send ... */
572617

573-
if (nanosleep(&sleep_ts, NULL))
618+
if (!gap_from_file && nanosleep(&sleep_ts, NULL))
574619
return 1;
575620

576621
delay_loops++; /* private statistics */

0 commit comments

Comments
 (0)