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 );
@@ -117,6 +124,8 @@ static void print_usage(char *prg)
117
124
"loopback of sent CAN frames)\n" );
118
125
fprintf (stderr , " -v (verbose: print "
119
126
"sent CAN frames)\n" );
127
+ fprintf (stderr , " -r (real-time: send "
128
+ "CAN frames in real-time)\n" );
120
129
fprintf (stderr , " -h (show "
121
130
"this help message)\n\n" );
122
131
fprintf (stderr , "Interface assignment:\n" );
@@ -254,6 +263,39 @@ static int add_assignment(char *mode, int socket, char *txname,
254
263
return 0 ;
255
264
}
256
265
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
+
257
299
int main (int argc , char * * argv )
258
300
{
259
301
static char buf [BUFSZ ], device [DEVSZ ], afrbuf [AFRSZ ];
@@ -280,8 +322,11 @@ int main(int argc, char **argv)
280
322
int eof , txmtu , i , j ;
281
323
char * fret ;
282
324
unsigned long long sec , usec ;
325
+ bool gap_from_file = false;
326
+ struct sleep timestamps ;
327
+ struct timeval send_time , act_time , init_time ;
283
328
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 ) {
285
330
switch (opt ) {
286
331
case 'I' :
287
332
infile = fopen (optarg , "r" );
@@ -336,6 +381,17 @@ int main(int argc, char **argv)
336
381
verbose ++ ;
337
382
break ;
338
383
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
+
339
395
case 'h' :
340
396
print_usage (basename (argv [0 ]));
341
397
exit (EXIT_SUCCESS );
@@ -368,8 +424,10 @@ int main(int argc, char **argv)
368
424
printf ("interactive mode: press ENTER to process next CAN frame ...\n" );
369
425
}
370
426
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
+ }
373
431
374
432
/* open socket */
375
433
if ((s = socket (PF_CAN , SOCK_RAW , CAN_RAW )) < 0 ) {
@@ -513,6 +571,23 @@ int main(int argc, char **argv)
513
571
addr .can_family = AF_CAN ;
514
572
addr .can_ifindex = txidx ; /* send via this interface */
515
573
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
+
516
591
if (sendto (s , & cu , txmtu , 0 , (struct sockaddr * )& addr , sizeof (addr )) != txmtu ) {
517
592
perror ("sendto" );
518
593
return 1 ;
@@ -570,7 +645,7 @@ int main(int argc, char **argv)
570
645
571
646
} /* while frames_to_send ... */
572
647
573
- if (nanosleep (& sleep_ts , NULL ))
648
+ if (! gap_from_file && nanosleep (& sleep_ts , NULL ))
574
649
return 1 ;
575
650
576
651
delay_loops ++ ; /* private statistics */
0 commit comments