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
9091extern int optind , opterr , optopt ;
9192
93+ struct sleep {
94+ struct timeval * sleep_vector ;
95+ size_t idx ;
96+ size_t size ;
97+ };
98+
9299static 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