48
48
#include <string.h>
49
49
#include <time.h>
50
50
#include <unistd.h>
51
+ #include <stdbool.h>
51
52
52
53
#include <linux/can.h>
53
54
#include <linux/can/raw.h>
@@ -89,6 +90,12 @@ const int canfx_on = 1;
89
90
90
91
extern int optind , opterr , optopt ;
91
92
93
+ struct sleep {
94
+ struct timeval * sleep_vector ;
95
+ size_t idx ;
96
+ size_t size ;
97
+ };
98
+
92
99
static void print_usage (char * prg )
93
100
{
94
101
fprintf (stderr , "%s - replay a compact CAN frame logfile to CAN devices.\n" , prg );
@@ -116,7 +123,9 @@ static void print_usage(char *prg)
116
123
fprintf (stderr , " -x (disable local "
117
124
"loopback of sent CAN frames)\n" );
118
125
fprintf (stderr , " -v (verbose: print "
119
- "sent CAN frames)\n\n" );
126
+ "sent CAN frames)\n" );
127
+ fprintf (stderr , " -r (real-time: send "
128
+ "CAN frames in real-time)\n\n" );
120
129
fprintf (stderr , "Interface assignment:\n" );
121
130
fprintf (stderr , " 0..n assignments like <write-if>=<log-if>\n\n" );
122
131
fprintf (stderr , " e.g. vcan2=can0 (send frames received from can0 on "
@@ -252,6 +261,38 @@ static int add_assignment(char *mode, int socket, char *txname,
252
261
return 0 ;
253
262
}
254
263
264
+ void load_gaps_from_file (FILE * fp , struct sleep * timestamps )
265
+ {
266
+ char * line = NULL ;
267
+ size_t len = 0 ;
268
+ ssize_t read ;
269
+
270
+ while ((read = getline (& line , & len , fp )) != -1 ) {
271
+ if (timestamps -> idx == timestamps -> size ) {
272
+ timestamps -> size ++ ;
273
+ timestamps -> sleep_vector = realloc (timestamps -> sleep_vector , timestamps -> size * sizeof (struct timeval ));
274
+ if (!timestamps -> sleep_vector ) {
275
+ fprintf (stderr , "Failed to create the timestamps vector!\n" );
276
+ exit (1 );
277
+ }
278
+ }
279
+ sscanf (line , "(%lu.%lu)" , & timestamps -> sleep_vector [timestamps -> idx ].tv_sec , & timestamps -> sleep_vector [timestamps -> idx ].tv_usec );
280
+ timestamps -> idx ++ ;
281
+ }
282
+ free (line );
283
+ }
284
+
285
+ void init_timestamps (struct sleep * timestamps , size_t init_size )
286
+ {
287
+ timestamps -> size = init_size ;
288
+ timestamps -> sleep_vector = calloc (init_size , sizeof (* (timestamps -> sleep_vector )));
289
+ if (!timestamps -> sleep_vector ) {
290
+ fprintf (stderr , "Failed to create the timestamps vector!\n" );
291
+ exit (1 );
292
+ }
293
+ timestamps -> idx = 0 ;
294
+ }
295
+
255
296
int main (int argc , char * * argv )
256
297
{
257
298
static char buf [BUFSZ ], device [DEVSZ ], afrbuf [AFRSZ ];
@@ -278,8 +319,11 @@ int main(int argc, char **argv)
278
319
int eof , txmtu , i , j ;
279
320
char * fret ;
280
321
unsigned long long sec , usec ;
322
+ bool gap_from_file = false;
323
+ struct sleep timestamps ;
324
+ struct timeval send_time , act_time , init_time ;
281
325
282
- while ((opt = getopt (argc , argv , "I:l:tin:g:s:xv ?" )) != -1 ) {
326
+ while ((opt = getopt (argc , argv , "I:l:tin:g:s:xvr ?" )) != -1 ) {
283
327
switch (opt ) {
284
328
case 'I' :
285
329
infile = fopen (optarg , "r" );
@@ -334,6 +378,17 @@ int main(int argc, char **argv)
334
378
verbose ++ ;
335
379
break ;
336
380
381
+ case 'r' :
382
+ if (!isatty (fileno (infile ))) {
383
+ fprintf (stderr , "Specify an input file for option -r !\n" );
384
+ exit (EXIT_FAILURE );
385
+ }
386
+ gap_from_file = true; /* using time delta from file */
387
+ init_timestamps (& timestamps , 1 );
388
+ load_gaps_from_file (infile , & timestamps );
389
+ timestamps .idx = 0 ;
390
+ break ;
391
+
337
392
case '?' :
338
393
default :
339
394
print_usage (basename (argv [0 ]));
@@ -362,8 +417,10 @@ int main(int argc, char **argv)
362
417
printf ("interactive mode: press ENTER to process next CAN frame ...\n" );
363
418
}
364
419
365
- sleep_ts .tv_sec = gap / 1000 ;
366
- sleep_ts .tv_nsec = (gap % 1000 ) * 1000000 ;
420
+ if (!gap_from_file ) {
421
+ sleep_ts .tv_sec = gap / 1000 ;
422
+ sleep_ts .tv_nsec = (gap % 1000 ) * 1000000 ;
423
+ }
367
424
368
425
/* open socket */
369
426
if ((s = socket (PF_CAN , SOCK_RAW , CAN_RAW )) < 0 ) {
@@ -507,6 +564,23 @@ int main(int argc, char **argv)
507
564
addr .can_family = AF_CAN ;
508
565
addr .can_ifindex = txidx ; /* send via this interface */
509
566
567
+ if (gap_from_file && timestamps .idx > 0 ) {
568
+ send_time = timestamps .sleep_vector [timestamps .idx ];
569
+ gettimeofday (& act_time , NULL );
570
+ timersub (& act_time , & init_time , & act_time );
571
+
572
+ while (timercmp (& act_time , & send_time , < )){
573
+ gettimeofday (& act_time , NULL );
574
+ timersub (& act_time , & init_time , & act_time );
575
+ }
576
+ }
577
+ if (gap_from_file && timestamps .idx == 0 ) {
578
+ gettimeofday (& init_time , NULL );
579
+ gettimeofday (& act_time , NULL );
580
+ timersub (& act_time , & init_time , & act_time );
581
+ }
582
+ timestamps .idx ++ ;
583
+
510
584
if (sendto (s , & cu , txmtu , 0 , (struct sockaddr * )& addr , sizeof (addr )) != txmtu ) {
511
585
perror ("sendto" );
512
586
return 1 ;
@@ -564,7 +638,7 @@ int main(int argc, char **argv)
564
638
565
639
} /* while frames_to_send ... */
566
640
567
- if (nanosleep (& sleep_ts , NULL ))
641
+ if (! gap_from_file && nanosleep (& sleep_ts , NULL ))
568
642
return 1 ;
569
643
570
644
delay_loops ++ ; /* private statistics */
0 commit comments