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" );
@@ -254,6 +263,39 @@ static int add_assignment(char *mode, int socket, char *txname,
254263 return 0 ;
255264}
256265
266+ static void load_gaps_from_file (FILE * fp , struct sleep * timestamps )
267+ {
268+ char * line = NULL ;
269+ size_t len = 0 ;
270+ ssize_t read ;
271+ struct timeval * current ;
272+
273+ while ((read = getline (& line , & len , fp )) != -1 ) {
274+ if (timestamps -> idx == timestamps -> size ) {
275+ timestamps -> size *= 2 ;
276+ timestamps -> sleep_vector = realloc (timestamps -> sleep_vector , timestamps -> size * sizeof (* (timestamps -> sleep_vector )));
277+ if (!timestamps -> sleep_vector ) {
278+ fprintf (stderr , "Failed to realloc the timestamps vector!\n" );
279+ exit (1 );
280+ }
281+ }
282+ current = & timestamps -> sleep_vector [timestamps -> idx ];
283+ sscanf (line , "(%lu.%lu)" , & (current -> tv_sec ), & (current -> tv_usec ));
284+ timestamps -> idx ++ ;
285+ }
286+ free (line );
287+ }
288+
289+ static void init_timestamps (struct sleep * timestamps , size_t init_size )
290+ {
291+ timestamps -> size = init_size ;
292+ timestamps -> sleep_vector = calloc (init_size , sizeof (* (timestamps -> sleep_vector )));
293+ if (!timestamps -> sleep_vector ) {
294+ fprintf (stderr , "Failed to create the timestamps vector!\n" );
295+ exit (1 );
296+ }
297+ }
298+
257299int main (int argc , char * * argv )
258300{
259301 static char buf [BUFSZ ], device [DEVSZ ], afrbuf [AFRSZ ];
@@ -280,8 +322,11 @@ int main(int argc, char **argv)
280322 int eof , txmtu , i , j ;
281323 char * fret ;
282324 unsigned long long sec , usec ;
325+ bool gap_from_file = false;
326+ struct sleep timestamps ;
327+ struct timeval send_time , act_time , init_time ;
283328
284- while ((opt = getopt (argc , argv , "I:l:tin:g:s:xvh " )) != -1 ) {
329+ while ((opt = getopt (argc , argv , "I:l:tin:g:s:xvrh " )) != -1 ) {
285330 switch (opt ) {
286331 case 'I' :
287332 infile = fopen (optarg , "r" );
@@ -336,6 +381,17 @@ int main(int argc, char **argv)
336381 verbose ++ ;
337382 break ;
338383
384+ case 'r' :
385+ if (isatty (fileno (infile ))) {
386+ fprintf (stderr , "Specify an input file for option -r !\n" );
387+ exit (EXIT_FAILURE );
388+ }
389+ gap_from_file = true; /* using time delta from file */
390+ init_timestamps (& timestamps , 1 );
391+ load_gaps_from_file (infile , & timestamps );
392+ timestamps .idx = 0 ; /*to avoid warning accessing idx variable*/
393+ break ;
394+
339395 case 'h' :
340396 print_usage (basename (argv [0 ]));
341397 exit (EXIT_SUCCESS );
@@ -368,8 +424,10 @@ int main(int argc, char **argv)
368424 printf ("interactive mode: press ENTER to process next CAN frame ...\n" );
369425 }
370426
371- sleep_ts .tv_sec = gap / 1000 ;
372- sleep_ts .tv_nsec = (gap % 1000 ) * 1000000 ;
427+ if (!gap_from_file ) {
428+ sleep_ts .tv_sec = gap / 1000 ;
429+ sleep_ts .tv_nsec = (gap % 1000 ) * 1000000 ;
430+ }
373431
374432 /* open socket */
375433 if ((s = socket (PF_CAN , SOCK_RAW , CAN_RAW )) < 0 ) {
@@ -513,6 +571,23 @@ int main(int argc, char **argv)
513571 addr .can_family = AF_CAN ;
514572 addr .can_ifindex = txidx ; /* send via this interface */
515573
574+ if (gap_from_file && timestamps .idx > 0 ) {
575+ send_time = timestamps .sleep_vector [timestamps .idx ];
576+ gettimeofday (& act_time , NULL );
577+ timersub (& act_time , & init_time , & act_time );
578+
579+ while (timercmp (& act_time , & send_time , < )){
580+ gettimeofday (& act_time , NULL );
581+ timersub (& act_time , & init_time , & act_time );
582+ }
583+ }
584+ if (gap_from_file && timestamps .idx == 0 ) {
585+ gettimeofday (& init_time , NULL );
586+ gettimeofday (& act_time , NULL );
587+ timersub (& act_time , & init_time , & act_time );
588+ }
589+ timestamps .idx ++ ;
590+
516591 if (sendto (s , & cu , txmtu , 0 , (struct sockaddr * )& addr , sizeof (addr )) != txmtu ) {
517592 perror ("sendto" );
518593 return 1 ;
@@ -570,7 +645,7 @@ int main(int argc, char **argv)
570645
571646 } /* while frames_to_send ... */
572647
573- if (nanosleep (& sleep_ts , NULL ))
648+ if (! gap_from_file && nanosleep (& sleep_ts , NULL ))
574649 return 1 ;
575650
576651 delay_loops ++ ; /* private statistics */
0 commit comments