Whitespace fixes. Indented the code following Linux styleguide to fix

the mess between tabs and spaces.
pull/7/head
Oliver Hartkopp 2008-06-03 08:46:57 +00:00
parent 8a5c0365e6
commit adbe6f9bee
12 changed files with 2560 additions and 2560 deletions

428
asc2log.c
View File

@ -65,272 +65,272 @@ extern int optind, opterr, optopt;
void print_usage(char *prg) void print_usage(char *prg)
{ {
fprintf(stderr, "Usage: %s\n", prg); fprintf(stderr, "Usage: %s\n", prg);
fprintf(stderr, "Options: -I <infile> (default stdin)\n"); fprintf(stderr, "Options: -I <infile> (default stdin)\n");
fprintf(stderr, " -O <outfile> (default stdout)\n"); fprintf(stderr, " -O <outfile> (default stdout)\n");
} }
void prframe(FILE *file, struct timeval *tv, int dev, struct can_frame *cf) { void prframe(FILE *file, struct timeval *tv, int dev, struct can_frame *cf) {
fprintf(file, "(%ld.%06ld) ", tv->tv_sec, tv->tv_usec); fprintf(file, "(%ld.%06ld) ", tv->tv_sec, tv->tv_usec);
if (dev > 0) if (dev > 0)
fprintf(file, "can%d ", dev-1); fprintf(file, "can%d ", dev-1);
else else
fprintf(file, "canX "); fprintf(file, "canX ");
fprint_canframe(file, cf, "\n", 0); fprint_canframe(file, cf, "\n", 0);
} }
void get_can_id(struct can_frame *cf, char *idstring, int base) { void get_can_id(struct can_frame *cf, char *idstring, int base) {
if (idstring[strlen(idstring)-1] == 'x') { if (idstring[strlen(idstring)-1] == 'x') {
cf->can_id = CAN_EFF_FLAG; cf->can_id = CAN_EFF_FLAG;
idstring[strlen(idstring)-1] = 0; idstring[strlen(idstring)-1] = 0;
} else } else
cf->can_id = 0; cf->can_id = 0;
cf->can_id |= strtoul(idstring, NULL, base); cf->can_id |= strtoul(idstring, NULL, base);
} }
void calc_tv(struct timeval *tv, struct timeval *read_tv, void calc_tv(struct timeval *tv, struct timeval *read_tv,
struct timeval *date_tv, char timestamps, int dplace) { struct timeval *date_tv, char timestamps, int dplace) {
if (dplace == 4) /* shift values having only 4 decimal places */ if (dplace == 4) /* shift values having only 4 decimal places */
read_tv->tv_usec *= 100; /* and need for 6 */ read_tv->tv_usec *= 100; /* and need for 6 */
if (timestamps == 'a') { /* absolute */ if (timestamps == 'a') { /* absolute */
tv->tv_sec = date_tv->tv_sec + read_tv->tv_sec; tv->tv_sec = date_tv->tv_sec + read_tv->tv_sec;
tv->tv_usec = date_tv->tv_usec + read_tv->tv_usec; tv->tv_usec = date_tv->tv_usec + read_tv->tv_usec;
} else { /* relative */ } else { /* relative */
if (((!tv->tv_sec) && (!tv->tv_usec)) && if (((!tv->tv_sec) && (!tv->tv_usec)) &&
(date_tv->tv_sec || date_tv->tv_usec)) { (date_tv->tv_sec || date_tv->tv_usec)) {
tv->tv_sec = date_tv->tv_sec; /* initial date/time */ tv->tv_sec = date_tv->tv_sec; /* initial date/time */
tv->tv_usec = date_tv->tv_usec; tv->tv_usec = date_tv->tv_usec;
}
tv->tv_sec += read_tv->tv_sec;
tv->tv_usec += read_tv->tv_usec;
} }
tv->tv_sec += read_tv->tv_sec; if (tv->tv_usec > 1000000) {
tv->tv_usec += read_tv->tv_usec; tv->tv_usec -= 1000000;
} tv->tv_sec++;
}
if (tv->tv_usec > 1000000) {
tv->tv_usec -= 1000000;
tv->tv_sec++;
}
} }
int get_date(struct timeval *tv, char *date) { int get_date(struct timeval *tv, char *date) {
char ctmp[10]; char ctmp[10];
int itmp; int itmp;
struct tm tms; struct tm tms;
if (sscanf(date, "%9s %d %9s %9s %d", ctmp, &itmp, ctmp, ctmp, &itmp) == 5) { if (sscanf(date, "%9s %d %9s %9s %d", ctmp, &itmp, ctmp, ctmp, &itmp) == 5) {
/* assume EN/US date due to existing am/pm field */ /* assume EN/US date due to existing am/pm field */
if (!setlocale(LC_TIME, "en_US")) if (!setlocale(LC_TIME, "en_US"))
return 1; return 1;
if (!strptime(date, "%B %d %r %Y", &tms)) if (!strptime(date, "%B %d %r %Y", &tms))
return 1; return 1;
} else { } else {
/* assume DE date due to non existing am/pm field */ /* assume DE date due to non existing am/pm field */
if (sscanf(date, "%9s %d %9s %d", ctmp, &itmp, ctmp, &itmp) != 4) if (sscanf(date, "%9s %d %9s %d", ctmp, &itmp, ctmp, &itmp) != 4)
return 1; return 1;
if (!setlocale(LC_TIME, "de_DE")) if (!setlocale(LC_TIME, "de_DE"))
return 1; return 1;
if (!strptime(date, "%B %d %T %Y", &tms)) if (!strptime(date, "%B %d %T %Y", &tms))
return 1; return 1;
} }
//printf("h %d m %d s %d d %d m %d y %d\n", //printf("h %d m %d s %d d %d m %d y %d\n",
//tms.tm_hour, tms.tm_min, tms.tm_sec, //tms.tm_hour, tms.tm_min, tms.tm_sec,
//tms.tm_mday, tms.tm_mon+1, tms.tm_year+1900); //tms.tm_mday, tms.tm_mon+1, tms.tm_year+1900);
tv->tv_sec = mktime(&tms); tv->tv_sec = mktime(&tms);
if (tv->tv_sec < 0) if (tv->tv_sec < 0)
return 1; return 1;
return 0; return 0;
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
char buf[100], tmp1[100], tmp2[100]; char buf[100], tmp1[100], tmp2[100];
FILE *infile = stdin; FILE *infile = stdin;
FILE *outfile = stdout; FILE *outfile = stdout;
static int verbose; static int verbose;
struct can_frame cf; struct can_frame cf;
static struct timeval tv; /* current frame timestamp */ static struct timeval tv; /* current frame timestamp */
static struct timeval read_tv; /* frame timestamp from ASC file */ static struct timeval read_tv; /* frame timestamp from ASC file */
static struct timeval date_tv; /* date of the ASC file */ static struct timeval date_tv; /* date of the ASC file */
static int dplace; /* decimal place 4 or 6 or uninitialized */ static int dplace; /* decimal place 4 or 6 or uninitialized */
static char base; /* 'd'ec or 'h'ex */ static char base; /* 'd'ec or 'h'ex */
static char timestamps; /* 'a'bsolute or 'r'elative */ static char timestamps; /* 'a'bsolute or 'r'elative */
int interface; int interface;
char rtr; char rtr;
int dlc = 0; int dlc = 0;
int data[8]; int data[8];
int i, found, opt; int i, found, opt;
while ((opt = getopt(argc, argv, "I:O:v")) != -1) { while ((opt = getopt(argc, argv, "I:O:v")) != -1) {
switch (opt) { switch (opt) {
case 'I': case 'I':
infile = fopen(optarg, "r"); infile = fopen(optarg, "r");
if (!infile) { if (!infile) {
perror("infile"); perror("infile");
return 1; return 1;
} }
break; break;
case 'O': case 'O':
outfile = fopen(optarg, "w"); outfile = fopen(optarg, "w");
if (!outfile) { if (!outfile) {
perror("outfile"); perror("outfile");
return 1; return 1;
} }
break; break;
case 'v': case 'v':
verbose = 1; verbose = 1;
break; break;
default: default:
fprintf(stderr, "Unknown option %c\n", opt); fprintf(stderr, "Unknown option %c\n", opt);
print_usage(basename(argv[0])); print_usage(basename(argv[0]));
return 1; return 1;
break; break;
}
}
while (fgets(buf, 99, infile)) {
if (!dplace) { /* the representation of a valid CAN frame not known */
/* check for base and timestamp entries in the header */
if ((!base) &&
(sscanf(buf, "base %s timestamps %s", tmp1, tmp2) == 2)) {
base = tmp1[0];
timestamps = tmp2[0];
if (verbose)
printf("base %c timestamps %c\n", base, timestamps);
if ((base != 'h') && (base != 'd')) {
printf("invalid base %s (must be 'hex' or 'dez')!\n",
tmp1);
return 1;
} }
if ((timestamps != 'a') && (timestamps != 'r')) { }
printf("invalid timestamps %s (must be 'absolute'"
" or 'relative')!\n", tmp2);
return 1; while (fgets(buf, 99, infile)) {
if (!dplace) { /* the representation of a valid CAN frame not known */
/* check for base and timestamp entries in the header */
if ((!base) &&
(sscanf(buf, "base %s timestamps %s", tmp1, tmp2) == 2)) {
base = tmp1[0];
timestamps = tmp2[0];
if (verbose)
printf("base %c timestamps %c\n", base, timestamps);
if ((base != 'h') && (base != 'd')) {
printf("invalid base %s (must be 'hex' or 'dez')!\n",
tmp1);
return 1;
}
if ((timestamps != 'a') && (timestamps != 'r')) {
printf("invalid timestamps %s (must be 'absolute'"
" or 'relative')!\n", tmp2);
return 1;
}
continue;
}
/* check for the original logging date in the header */
if ((!date_tv.tv_sec) &&
(!strncmp(buf, "date", 4))) {
if (get_date(&date_tv, &buf[9])) { /* skip 'date day ' */
fprintf(stderr, "Not able to determine original log "
"file date. Using current time.\n");
/* use current date as default */
gettimeofday(&date_tv, NULL);
}
if (verbose)
printf("date %ld => %s", date_tv.tv_sec, ctime(&date_tv.tv_sec));
continue;
}
/* check for decimal places length in valid CAN frames */
if (sscanf(buf, "%ld.%s %d ", &tv.tv_sec, tmp2, &i) == 3){
dplace = strlen(tmp2);
if (verbose)
printf("decimal place %d, e.g. '%s'\n", dplace, tmp2);
if ((dplace != 4) && (dplace != 6)) {
printf("invalid dplace %d (must be 4 or 6)!\n", dplace);
return 1;
}
} else
continue; /* dplace remains zero until first found CAN frame */
} }
continue;
}
/* check for the original logging date in the header */ /* the representation of a valid CAN frame is known here */
if ((!date_tv.tv_sec) && /* so try to get CAN frames and ErrorFrames and convert them */
(!strncmp(buf, "date", 4))) {
if (get_date(&date_tv, &buf[9])) { /* skip 'date day ' */ /* 0.002367 1 390x Rx d 8 17 00 14 00 C0 00 08 00 */
fprintf(stderr, "Not able to determine original log "
"file date. Using current time.\n"); found = 0; /* found valid CAN frame ? */
/* use current date as default */
gettimeofday(&date_tv, NULL); if (base == 'h') { /* check for CAN frames with hexadecimal values */
if (sscanf(buf, "%ld.%ld %d %s %*s %c %d %x %x %x %x %x %x %x %x",
&read_tv.tv_sec, &read_tv.tv_usec, &interface,
tmp1, &rtr, &dlc,
&data[0], &data[1], &data[2], &data[3],
&data[4], &data[5], &data[6], &data[7]
) == dlc + 6 ) {
found = 1;
get_can_id(&cf, tmp1, 16);
}
} else { /* check for CAN frames with decimal values */
if (sscanf(buf, "%ld.%ld %d %s %*s %c %d %d %d %d %d %d %d %d %d",
&read_tv.tv_sec, &read_tv.tv_usec, &interface,
tmp1, &rtr, &dlc,
&data[0], &data[1], &data[2], &data[3],
&data[4], &data[5], &data[6], &data[7]
) == dlc + 6 ) {
found = 1;
get_can_id(&cf, tmp1, 10);
}
} }
if (verbose)
printf("date %ld => %s", date_tv.tv_sec, ctime(&date_tv.tv_sec));
continue;
}
/* check for decimal places length in valid CAN frames */ if (found) {
if (sscanf(buf, "%ld.%s %d ", &tv.tv_sec, tmp2, &i) == 3){ if (rtr == 'r')
dplace = strlen(tmp2); cf.can_id |= CAN_RTR_FLAG;
if (verbose)
printf("decimal place %d, e.g. '%s'\n", dplace, tmp2); cf.can_dlc = dlc & 0x0FU;
if ((dplace != 4) && (dplace != 6)) { for (i=0; i<dlc; i++)
printf("invalid dplace %d (must be 4 or 6)!\n", dplace); cf.data[i] = data[i] & 0xFFU;
return 1;
calc_tv(&tv, &read_tv, &date_tv, timestamps, dplace);
prframe(outfile, &tv, interface, &cf);
fflush(outfile);
continue;
}
/* check for ErrorFrames */
if (sscanf(buf, "%ld.%ld %d %s",
&read_tv.tv_sec, &read_tv.tv_usec,
&interface, tmp1) == 4) {
if (!strncmp(tmp1, "ErrorFrame", strlen("ErrorFrame"))) {
memset(&cf, 0, sizeof(cf));
/* do not know more than 'Error' */
cf.can_id = (CAN_ERR_FLAG | CAN_ERR_BUSERROR);
cf.can_dlc = CAN_ERR_DLC;
calc_tv(&tv, &read_tv, &date_tv, timestamps, dplace);
prframe(outfile, &tv, interface, &cf);
fflush(outfile);
}
} }
} else
continue; /* dplace remains zero until first found CAN frame */
} }
fclose(outfile);
/* the representation of a valid CAN frame is known here */ return 0;
/* so try to get CAN frames and ErrorFrames and convert them */
/* 0.002367 1 390x Rx d 8 17 00 14 00 C0 00 08 00 */
found = 0; /* found valid CAN frame ? */
if (base == 'h') { /* check for CAN frames with hexadecimal values */
if (sscanf(buf, "%ld.%ld %d %s %*s %c %d %x %x %x %x %x %x %x %x",
&read_tv.tv_sec, &read_tv.tv_usec, &interface,
tmp1, &rtr, &dlc,
&data[0], &data[1], &data[2], &data[3],
&data[4], &data[5], &data[6], &data[7]
) == dlc + 6 ) {
found = 1;
get_can_id(&cf, tmp1, 16);
}
} else { /* check for CAN frames with decimal values */
if (sscanf(buf, "%ld.%ld %d %s %*s %c %d %d %d %d %d %d %d %d %d",
&read_tv.tv_sec, &read_tv.tv_usec, &interface,
tmp1, &rtr, &dlc,
&data[0], &data[1], &data[2], &data[3],
&data[4], &data[5], &data[6], &data[7]
) == dlc + 6 ) {
found = 1;
get_can_id(&cf, tmp1, 10);
}
}
if (found) {
if (rtr == 'r')
cf.can_id |= CAN_RTR_FLAG;
cf.can_dlc = dlc & 0x0FU;
for (i=0; i<dlc; i++)
cf.data[i] = data[i] & 0xFFU;
calc_tv(&tv, &read_tv, &date_tv, timestamps, dplace);
prframe(outfile, &tv, interface, &cf);
fflush(outfile);
continue;
}
/* check for ErrorFrames */
if (sscanf(buf, "%ld.%ld %d %s",
&read_tv.tv_sec, &read_tv.tv_usec,
&interface, tmp1) == 4) {
if (!strncmp(tmp1, "ErrorFrame", strlen("ErrorFrame"))) {
memset(&cf, 0, sizeof(cf));
/* do not know more than 'Error' */
cf.can_id = (CAN_ERR_FLAG | CAN_ERR_BUSERROR);
cf.can_dlc = CAN_ERR_DLC;
calc_tv(&tv, &read_tv, &date_tv, timestamps, dplace);
prframe(outfile, &tv, interface, &cf);
fflush(outfile);
}
}
}
fclose(outfile);
return 0;
} }

View File

@ -74,11 +74,11 @@
extern int optind, opterr, optopt; extern int optind, opterr, optopt;
static struct { static struct {
char devname[IFNAMSIZ+1]; char devname[IFNAMSIZ+1];
unsigned int bitrate; unsigned int bitrate;
unsigned int recv_frames; unsigned int recv_frames;
unsigned int recv_bits_total; unsigned int recv_bits_total;
unsigned int recv_bits_payload; unsigned int recv_bits_payload;
} stat[MAXSOCK+1]; } stat[MAXSOCK+1];
static int max_devname_len; /* to prevent frazzled device name output */ static int max_devname_len; /* to prevent frazzled device name output */
@ -92,289 +92,289 @@ static char *prg;
void print_usage(char *prg) void print_usage(char *prg)
{ {
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg); fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg); fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg);
fprintf(stderr, "Options: -t (show current time on the first line)\n"); fprintf(stderr, "Options: -t (show current time on the first line)\n");
fprintf(stderr, " -c (colorize lines)\n"); fprintf(stderr, " -c (colorize lines)\n");
fprintf(stderr, " -b (show bargraph in %d%% resolution)\n", PERCENTRES); fprintf(stderr, " -b (show bargraph in %d%% resolution)\n", PERCENTRES);
fprintf(stderr, " -r (redraw the terminal - similar to top)\n"); fprintf(stderr, " -r (redraw the terminal - similar to top)\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "Up to %d CAN interfaces with mandatory bitrate can be specified on the \n", MAXSOCK); fprintf(stderr, "Up to %d CAN interfaces with mandatory bitrate can be specified on the \n", MAXSOCK);
fprintf(stderr, "commandline in the form: <ifname>@<bitrate>\n\n"); fprintf(stderr, "commandline in the form: <ifname>@<bitrate>\n\n");
fprintf(stderr, "The bitrate is mandatory as it is needed to know the CAN bus bitrate to\n"); fprintf(stderr, "The bitrate is mandatory as it is needed to know the CAN bus bitrate to\n");
fprintf(stderr, "calcultate the bus load percentage based on the received CAN frames.\n"); fprintf(stderr, "calcultate the bus load percentage based on the received CAN frames.\n");
fprintf(stderr, "For each given interface the data is presented in one line which contains:\n\n"); fprintf(stderr, "For each given interface the data is presented in one line which contains:\n\n");
fprintf(stderr, "(interface) (received CAN frames) (used bits total) (used bits for payload)\n"); fprintf(stderr, "(interface) (received CAN frames) (used bits total) (used bits for payload)\n");
fprintf(stderr, "\nExample:\n"); fprintf(stderr, "\nExample:\n");
fprintf(stderr, "\nuser$> canbusload can0@100000 can1@500000 can2@500000 can3@500000 -r -t -b -c\n\n"); fprintf(stderr, "\nuser$> canbusload can0@100000 can1@500000 can2@500000 can3@500000 -r -t -b -c\n\n");
fprintf(stderr, "%s 2008-05-27 15:18:49\n", prg); fprintf(stderr, "%s 2008-05-27 15:18:49\n", prg);
fprintf(stderr, " can0@100000 805 74491 36656 74%% |XXXXXXXXXXXXXX......|\n"); fprintf(stderr, " can0@100000 805 74491 36656 74%% |XXXXXXXXXXXXXX......|\n");
fprintf(stderr, " can1@500000 796 75140 37728 15%% |XXX.................|\n"); fprintf(stderr, " can1@500000 796 75140 37728 15%% |XXX.................|\n");
fprintf(stderr, " can2@500000 0 0 0 0%% |....................|\n"); fprintf(stderr, " can2@500000 0 0 0 0%% |....................|\n");
fprintf(stderr, " can3@500000 47 4633 2424 0%% |....................|\n"); fprintf(stderr, " can3@500000 47 4633 2424 0%% |....................|\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
void sigterm(int signo) void sigterm(int signo)
{ {
exit(0); exit(0);
} }
void printstats(int signo) void printstats(int signo)
{ {
int i, j, percent; int i, j, percent;
if (redraw) if (redraw)
printf("%s", CSR_HOME); printf("%s", CSR_HOME);
if (timestamp) { if (timestamp) {
time_t currtime; time_t currtime;
struct tm now; struct tm now;
if (time(&currtime) == (time_t)-1) { if (time(&currtime) == (time_t)-1) {
perror("time"); perror("time");
exit(1); exit(1);
}
localtime_r(&currtime, &now);
printf("%s %04d-%02d-%02d %02d:%02d:%02d\n",
prg,
now.tm_year + 1900,
now.tm_mon + 1,
now.tm_mday,
now.tm_hour,
now.tm_min,
now.tm_sec);
} }
localtime_r(&currtime, &now); for (i=0; i<currmax; i++) {
printf("%s %04d-%02d-%02d %02d:%02d:%02d\n", if (color)
prg, if (i%2)
now.tm_year + 1900, printf("%s", FGRED);
now.tm_mon + 1, else
now.tm_mday, printf("%s", FGBLUE);
now.tm_hour,
now.tm_min,
now.tm_sec);
}
for (i=0; i<currmax; i++) { if (stat[i].bitrate)
percent = (stat[i].recv_bits_total*100)/stat[i].bitrate;
if (color)
if (i%2)
printf("%s", FGRED);
else
printf("%s", FGBLUE);
if (stat[i].bitrate)
percent = (stat[i].recv_bits_total*100)/stat[i].bitrate;
else
percent = 0;
printf(" %*s@%-*d %4d %6d %6d %3d%%",
max_devname_len, stat[i].devname,
max_bitrate_len, stat[i].bitrate,
stat[i].recv_frames,
stat[i].recv_bits_total,
stat[i].recv_bits_payload,
percent);
if (bargraph) {
printf(" |");
for (j=0; j < NUMBAR; j++){
if (j < percent/PERCENTRES)
printf("X");
else else
printf("."); percent = 0;
}
printf("|"); printf(" %*s@%-*d %4d %6d %6d %3d%%",
max_devname_len, stat[i].devname,
max_bitrate_len, stat[i].bitrate,
stat[i].recv_frames,
stat[i].recv_bits_total,
stat[i].recv_bits_payload,
percent);
if (bargraph) {
printf(" |");
for (j=0; j < NUMBAR; j++){
if (j < percent/PERCENTRES)
printf("X");
else
printf(".");
}
printf("|");
}
if (color)
printf("%s", ATTRESET);
printf("\n");
stat[i].recv_frames = 0;
stat[i].recv_bits_total = 0;
stat[i].recv_bits_payload = 0;
} }
if (color)
printf("%s", ATTRESET);
printf("\n"); printf("\n");
stat[i].recv_frames = 0; alarm(1);
stat[i].recv_bits_total = 0;
stat[i].recv_bits_payload = 0;
}
printf("\n");
alarm(1);
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
fd_set rdfs; fd_set rdfs;
int s[MAXSOCK]; int s[MAXSOCK];
int opt; int opt;
char *ptr, *nptr; char *ptr, *nptr;
struct sockaddr_can addr; struct sockaddr_can addr;
struct can_frame frame; struct can_frame frame;
int nbytes, i; int nbytes, i;
struct ifreq ifr; struct ifreq ifr;
sigset_t sigmask, savesigmask; sigset_t sigmask, savesigmask;
signal(SIGTERM, sigterm); signal(SIGTERM, sigterm);
signal(SIGHUP, sigterm); signal(SIGHUP, sigterm);
signal(SIGINT, sigterm); signal(SIGINT, sigterm);
signal(SIGALRM, printstats); signal(SIGALRM, printstats);
prg = basename(argv[0]); prg = basename(argv[0]);
while ((opt = getopt(argc, argv, "rtbch?")) != -1) { while ((opt = getopt(argc, argv, "rtbch?")) != -1) {
switch (opt) { switch (opt) {
case 'r': case 'r':
redraw = 1; redraw = 1;
break; break;
case 't': case 't':
timestamp = 1; timestamp = 1;
break; break;
case 'b': case 'b':
bargraph = 1; bargraph = 1;
break; break;
case 'c': case 'c':
color = 1; color = 1;
break; break;
default: default:
print_usage(prg); print_usage(prg);
exit(1); exit(1);
break; break;
}
} }
}
if (optind == argc) { if (optind == argc) {
print_usage(prg); print_usage(prg);
exit(0); exit(0);
}
currmax = argc - optind; /* find real number of CAN devices */
if (currmax > MAXSOCK) {
printf("More than %d CAN devices given on commandline!\n", MAXSOCK);
return 1;
}
for (i=0; i < currmax; i++) {
ptr = argv[optind+i];
nbytes = strlen(ptr);
if (nbytes >= IFNAMSIZ+sizeof("@1000000")+1) {
printf("name of CAN device '%s' is too long!\n", ptr);
return 1;
} }
currmax = argc - optind; /* find real number of CAN devices */
if (currmax > MAXSOCK) {
printf("More than %d CAN devices given on commandline!\n", MAXSOCK);
return 1;
}
for (i=0; i < currmax; i++) {
ptr = argv[optind+i];
nbytes = strlen(ptr);
if (nbytes >= IFNAMSIZ+sizeof("@1000000")+1) {
printf("name of CAN device '%s' is too long!\n", ptr);
return 1;
}
#ifdef DEBUG #ifdef DEBUG
printf("open %d '%s'.\n", i, ptr); printf("open %d '%s'.\n", i, ptr);
#endif #endif
s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW); s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (s[i] < 0) { if (s[i] < 0) {
perror("socket"); perror("socket");
return 1; return 1;
} }
nptr = strchr(ptr, '@'); nptr = strchr(ptr, '@');
if (!nptr) { if (!nptr) {
print_usage(prg); print_usage(prg);
return 1; return 1;
} }
nbytes = nptr - ptr; /* interface name is up the first '@' */ nbytes = nptr - ptr; /* interface name is up the first '@' */
if (nbytes >= IFNAMSIZ) { if (nbytes >= IFNAMSIZ) {
printf("name of CAN device '%s' is too long!\n", ptr); printf("name of CAN device '%s' is too long!\n", ptr);
return 1; return 1;
} }
strncpy(stat[i].devname, ptr, nbytes); strncpy(stat[i].devname, ptr, nbytes);
memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name)); memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
strncpy(ifr.ifr_name, ptr, nbytes); strncpy(ifr.ifr_name, ptr, nbytes);
if (nbytes > max_devname_len) if (nbytes > max_devname_len)
max_devname_len = nbytes; /* for nice printing */ max_devname_len = nbytes; /* for nice printing */
stat[i].bitrate = atoi(nptr+1); /* bitrate is placed behind the '@' */ stat[i].bitrate = atoi(nptr+1); /* bitrate is placed behind the '@' */
if (!stat[i].bitrate || stat[i].bitrate > 1000000) { if (!stat[i].bitrate || stat[i].bitrate > 1000000) {
printf("invalid bitrate for CAN device '%s'!\n", ptr); printf("invalid bitrate for CAN device '%s'!\n", ptr);
return 1; return 1;
} }
nbytes = strlen(nptr+1); nbytes = strlen(nptr+1);
if (nbytes > max_bitrate_len) if (nbytes > max_bitrate_len)
max_bitrate_len = nbytes; /* for nice printing */ max_bitrate_len = nbytes; /* for nice printing */
#ifdef DEBUG #ifdef DEBUG
printf("using interface name '%s'.\n", ifr.ifr_name); printf("using interface name '%s'.\n", ifr.ifr_name);
#endif #endif
if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) { if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX"); perror("SIOCGIFINDEX");
exit(1); exit(1);
}
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind");
return 1;
}
} }
addr.can_family = AF_CAN; alarm(1);
addr.can_ifindex = ifr.ifr_ifindex;
if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) { if (redraw)
perror("bind"); printf("%s", CLR_SCREEN);
return 1;
while (1) {
FD_ZERO(&rdfs);
for (i=0; i<currmax; i++)
FD_SET(s[i], &rdfs);
savesigmask = sigmask;
if (pselect(s[currmax-1]+1, &rdfs, NULL, NULL, NULL, &sigmask) < 0) {
//perror("pselect");
sigmask = savesigmask;
continue;
}
for (i=0; i<currmax; i++) { /* check all CAN RAW sockets */
if (FD_ISSET(s[i], &rdfs)) {
nbytes = read(s[i], &frame, sizeof(struct can_frame));
if (nbytes < 0) {
perror("read");
return 1;
}
if (nbytes < sizeof(struct can_frame)) {
fprintf(stderr, "read: incomplete CAN frame\n");
return 1;
}
stat[i].recv_frames++;
stat[i].recv_bits_payload += frame.can_dlc*8;
stat[i].recv_bits_total += frame.can_dlc*8;
if (frame.can_id & CAN_EFF_FLAG)
stat[i].recv_bits_total += 67;
else
stat[i].recv_bits_total += 47;
}
}
} }
}
alarm(1);
if (redraw)
printf("%s", CLR_SCREEN);
while (1) {
FD_ZERO(&rdfs);
for (i=0; i<currmax; i++) for (i=0; i<currmax; i++)
FD_SET(s[i], &rdfs); close(s[i]);
savesigmask = sigmask; return 0;
if (pselect(s[currmax-1]+1, &rdfs, NULL, NULL, NULL, &sigmask) < 0) {
//perror("pselect");
sigmask = savesigmask;
continue;
}
for (i=0; i<currmax; i++) { /* check all CAN RAW sockets */
if (FD_ISSET(s[i], &rdfs)) {
nbytes = read(s[i], &frame, sizeof(struct can_frame));
if (nbytes < 0) {
perror("read");
return 1;
}
if (nbytes < sizeof(struct can_frame)) {
fprintf(stderr, "read: incomplete CAN frame\n");
return 1;
}
stat[i].recv_frames++;
stat[i].recv_bits_payload += frame.can_dlc*8;
stat[i].recv_bits_total += frame.can_dlc*8;
if (frame.can_id & CAN_EFF_FLAG)
stat[i].recv_bits_total += 67;
else
stat[i].recv_bits_total += 47;
}
}
}
for (i=0; i<currmax; i++)
close(s[i]);
return 0;
} }

830
candump.c
View File

@ -98,476 +98,476 @@ static volatile int running = 1;
void print_usage(char *prg) void print_usage(char *prg)
{ {
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg); fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg); fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg);
fprintf(stderr, "Options: -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n"); fprintf(stderr, "Options: -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n");
fprintf(stderr, " -c (increment color mode level)\n"); fprintf(stderr, " -c (increment color mode level)\n");
fprintf(stderr, " -i (binary output - may exceed 80 chars/line)\n"); fprintf(stderr, " -i (binary output - may exceed 80 chars/line)\n");
fprintf(stderr, " -a (enable additional ASCII output)\n"); fprintf(stderr, " -a (enable additional ASCII output)\n");
fprintf(stderr, " -s <level> (silent mode - 1: animation 2: completely silent)\n"); fprintf(stderr, " -s <level> (silent mode - 1: animation 2: completely silent)\n");
fprintf(stderr, " -b <can> (bridge mode - send received frames to <can>)\n"); fprintf(stderr, " -b <can> (bridge mode - send received frames to <can>)\n");
fprintf(stderr, " -B <can> (bridge mode - like '-b' with disabled loopback)\n"); fprintf(stderr, " -B <can> (bridge mode - like '-b' with disabled loopback)\n");
fprintf(stderr, " -l (log CAN-frames into file)\n"); fprintf(stderr, " -l (log CAN-frames into file)\n");
fprintf(stderr, " -L (use log file format on stdout)\n"); fprintf(stderr, " -L (use log file format on stdout)\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "Up to %d CAN interfaces with optional filter sets can be specified\n", MAXSOCK); fprintf(stderr, "Up to %d CAN interfaces with optional filter sets can be specified\n", MAXSOCK);
fprintf(stderr, "on the commandline in the form: <ifname>[,filter]*\n"); fprintf(stderr, "on the commandline in the form: <ifname>[,filter]*\n");
fprintf(stderr, "\nUp to %d comma separated filters can be specified for each given CAN interface:\n", MAXFILTER); fprintf(stderr, "\nUp to %d comma separated filters can be specified for each given CAN interface:\n", MAXFILTER);
fprintf(stderr, " <can_id>:<can_mask> (matches when <received_can_id> & mask == can_id & mask)\n"); fprintf(stderr, " <can_id>:<can_mask> (matches when <received_can_id> & mask == can_id & mask)\n");
fprintf(stderr, " <can_id>~<can_mask> (matches when <received_can_id> & mask != can_id & mask)\n"); fprintf(stderr, " <can_id>~<can_mask> (matches when <received_can_id> & mask != can_id & mask)\n");
fprintf(stderr, " #<error_mask> (set error frame filter, see include/linux/can/error.h)\n"); fprintf(stderr, " #<error_mask> (set error frame filter, see include/linux/can/error.h)\n");
fprintf(stderr, "\nUse interface name '%s' to receive from all CAN interfaces.\n", ANYDEV); fprintf(stderr, "\nUse interface name '%s' to receive from all CAN interfaces.\n", ANYDEV);
fprintf(stderr, "CAN IDs, masks and data content are given and expected in hexadecimal values.\n"); fprintf(stderr, "CAN IDs, masks and data content are given and expected in hexadecimal values.\n");
fprintf(stderr, "\nExamples:\n"); fprintf(stderr, "\nExamples:\n");
fprintf(stderr, "%s -c -c -ta can0,123:7FF,400:700,#000000FF can2,400~7F0 can3 can8\n", prg); fprintf(stderr, "%s -c -c -ta can0,123:7FF,400:700,#000000FF can2,400~7F0 can3 can8\n", prg);
fprintf(stderr, "%s -l any,0~0,#FFFFFFFF (log only error frames but no(!) data frames)\n", prg); fprintf(stderr, "%s -l any,0~0,#FFFFFFFF (log only error frames but no(!) data frames)\n", prg);
fprintf(stderr, "%s vcan2,92345678:9FFFFFFF (match only for extended CAN ID 12345678)\n", prg); fprintf(stderr, "%s vcan2,92345678:9FFFFFFF (match only for extended CAN ID 12345678)\n", prg);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
void sigterm(int signo) void sigterm(int signo)
{ {
running = 0; running = 0;
} }
int idx2dindex(int ifidx, int socket) { int idx2dindex(int ifidx, int socket) {
int i; int i;
struct ifreq ifr; struct ifreq ifr;
for (i=0; i < MAXIFNAMES; i++) { for (i=0; i < MAXIFNAMES; i++) {
if (dindex[i] == ifidx) if (dindex[i] == ifidx)
return i; return i;
}
/* create new interface index cache entry */
/* remove index cache zombies first */
for (i=0; i < MAXIFNAMES; i++) {
if (dindex[i]) {
ifr.ifr_ifindex = dindex[i];
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
dindex[i] = 0;
} }
}
for (i=0; i < MAXIFNAMES; i++) /* create new interface index cache entry */
if (!dindex[i]) /* free entry */
break;
if (i == MAXIFNAMES) { /* remove index cache zombies first */
printf("Interface index cache only supports %d interfaces.\n", for (i=0; i < MAXIFNAMES; i++) {
MAXIFNAMES); if (dindex[i]) {
exit(1); ifr.ifr_ifindex = dindex[i];
} if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
dindex[i] = 0;
}
}
dindex[i] = ifidx; for (i=0; i < MAXIFNAMES; i++)
if (!dindex[i]) /* free entry */
break;
ifr.ifr_ifindex = ifidx; if (i == MAXIFNAMES) {
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0) printf("Interface index cache only supports %d interfaces.\n",
perror("SIOCGIFNAME"); MAXIFNAMES);
exit(1);
}
if (max_devname_len < strlen(ifr.ifr_name)) dindex[i] = ifidx;
max_devname_len = strlen(ifr.ifr_name);
strcpy(devname[i], ifr.ifr_name); ifr.ifr_ifindex = ifidx;
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
perror("SIOCGIFNAME");
if (max_devname_len < strlen(ifr.ifr_name))
max_devname_len = strlen(ifr.ifr_name);
strcpy(devname[i], ifr.ifr_name);
#ifdef DEBUG #ifdef DEBUG
printf("new index %d (%s)\n", i, devname[i]); printf("new index %d (%s)\n", i, devname[i]);
#endif #endif
return i; return i;
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
fd_set rdfs; fd_set rdfs;
int s[MAXSOCK]; int s[MAXSOCK];
int bridge = 0; int bridge = 0;
unsigned char timestamp = 0; unsigned char timestamp = 0;
unsigned char silent = 0; unsigned char silent = 0;
unsigned char silentani = 0; unsigned char silentani = 0;
unsigned char color = 0; unsigned char color = 0;
unsigned char view = 0; unsigned char view = 0;
unsigned char log = 0; unsigned char log = 0;
unsigned char logfrmt = 0; unsigned char logfrmt = 0;
int opt, ret; int opt, ret;
int currmax, numfilter; int currmax, numfilter;
char *ptr, *nptr; char *ptr, *nptr;
struct sockaddr_can addr; struct sockaddr_can addr;
struct can_filter rfilter[MAXFILTER]; struct can_filter rfilter[MAXFILTER];
can_err_mask_t err_mask; can_err_mask_t err_mask;
struct can_frame frame; struct can_frame frame;
int nbytes, i; int nbytes, i;
struct ifreq ifr; struct ifreq ifr;
struct timeval tv, last_tv; struct timeval tv, last_tv;
FILE *logfile = NULL; FILE *logfile = NULL;
signal(SIGTERM, sigterm); signal(SIGTERM, sigterm);
signal(SIGHUP, sigterm); signal(SIGHUP, sigterm);
signal(SIGINT, sigterm); signal(SIGINT, sigterm);
last_tv.tv_sec = 0; last_tv.tv_sec = 0;
last_tv.tv_usec = 0; last_tv.tv_usec = 0;
while ((opt = getopt(argc, argv, "t:cias:b:B:lLh?")) != -1) { while ((opt = getopt(argc, argv, "t:cias:b:B:lLh?")) != -1) {
switch (opt) { switch (opt) {
case 't': case 't':
timestamp = optarg[0]; timestamp = optarg[0];
if ((timestamp != 'a') && (timestamp != 'A') && if ((timestamp != 'a') && (timestamp != 'A') &&
(timestamp != 'd') && (timestamp != 'z')) { (timestamp != 'd') && (timestamp != 'z')) {
printf("%s: unknown timestamp mode '%c' - ignored\n", printf("%s: unknown timestamp mode '%c' - ignored\n",
basename(argv[0]), optarg[0]); basename(argv[0]), optarg[0]);
timestamp = 0; timestamp = 0;
} }
break; break;
case 'c': case 'c':
color++; color++;
break; break;
case 'i': case 'i':
view |= CANLIB_VIEW_BINARY; view |= CANLIB_VIEW_BINARY;
break; break;
case 'a': case 'a':
view |= CANLIB_VIEW_ASCII; view |= CANLIB_VIEW_ASCII;
break; break;
case 's': case 's':
silent = atoi(optarg); silent = atoi(optarg);
break; break;
case 'b': case 'b':
case 'B': case 'B':
if (strlen(optarg) >= IFNAMSIZ) { if (strlen(optarg) >= IFNAMSIZ) {
printf("Name of CAN device '%s' is too long!\n\n", optarg); printf("Name of CAN device '%s' is too long!\n\n", optarg);
return 1;
} else {
bridge = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (bridge < 0) {
perror("bridge socket");
return 1;
}
addr.can_family = AF_CAN;
strcpy(ifr.ifr_name, optarg);
if (ioctl(bridge, SIOCGIFINDEX, &ifr) < 0)
perror("SIOCGIFINDEX");
addr.can_ifindex = ifr.ifr_ifindex;
if (!addr.can_ifindex) {
perror("invalid bridge interface");
return 1;
}
if (opt == 'B') {
int loopback = 0;
setsockopt(bridge, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
&loopback, sizeof(loopback));
}
if (bind(bridge, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bridge bind");
return 1;
}
}
break;
case 'l':
log = 1;
break;
case 'L':
logfrmt = 1;
break;
default:
print_usage(basename(argv[0]));
exit(1);
break;
}
}
if (optind == argc) {
print_usage(basename(argv[0]));
exit(0);
}
currmax = argc - optind; /* find real number of CAN devices */
if (currmax > MAXSOCK) {
printf("More than %d CAN devices given on commandline!\n", MAXSOCK);
return 1; return 1;
} else { }
bridge = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (bridge < 0) { for (i=0; i < currmax; i++) {
perror("bridge socket");
return 1; ptr = argv[optind+i];
nptr = strchr(ptr, ',');
#ifdef DEBUG
printf("open %d '%s'.\n", i, ptr);
#endif
s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (s[i] < 0) {
perror("socket");
return 1;
} }
if (nptr)
nbytes = nptr - ptr; /* interface name is up the first ',' */
else
nbytes = strlen(ptr); /* no ',' found => no filter definitions */
if (nbytes >= IFNAMSIZ) {
printf("name of CAN device '%s' is too long!\n", ptr);
return 1;
}
if (nbytes > max_devname_len)
max_devname_len = nbytes; /* for nice printing */
addr.can_family = AF_CAN; addr.can_family = AF_CAN;
strcpy(ifr.ifr_name, optarg);
if (ioctl(bridge, SIOCGIFINDEX, &ifr) < 0)
perror("SIOCGIFINDEX");
addr.can_ifindex = ifr.ifr_ifindex;
if (!addr.can_ifindex) { memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
perror("invalid bridge interface"); strncpy(ifr.ifr_name, ptr, nbytes);
return 1;
}
if (opt == 'B') {
int loopback = 0;
setsockopt(bridge, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
&loopback, sizeof(loopback));
}
if (bind(bridge, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bridge bind");
return 1;
}
}
break;
case 'l':
log = 1;
break;
case 'L':
logfrmt = 1;
break;
default:
print_usage(basename(argv[0]));
exit(1);
break;
}
}
if (optind == argc) {
print_usage(basename(argv[0]));
exit(0);
}
currmax = argc - optind; /* find real number of CAN devices */
if (currmax > MAXSOCK) {
printf("More than %d CAN devices given on commandline!\n", MAXSOCK);
return 1;
}
for (i=0; i < currmax; i++) {
ptr = argv[optind+i];
nptr = strchr(ptr, ',');
#ifdef DEBUG #ifdef DEBUG
printf("open %d '%s'.\n", i, ptr); printf("using interface name '%s'.\n", ifr.ifr_name);
#endif #endif
s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW); if (strcmp(ANYDEV, ifr.ifr_name)) {
if (s[i] < 0) { if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
perror("socket"); perror("SIOCGIFINDEX");
return 1; exit(1);
}
addr.can_ifindex = ifr.ifr_ifindex;
} else
addr.can_ifindex = 0; /* any can interface */
if (nptr) {
/* found a ',' after the interface name => check for filters */
numfilter = 0;
err_mask = 0;
while (nptr) {
ptr = nptr+1; /* hop behind the ',' */
nptr = strchr(ptr, ','); /* update exit condition */
if (sscanf(ptr, "%lx:%lx",
(long unsigned int *)
&rfilter[numfilter].can_id,
(long unsigned int *)
&rfilter[numfilter].can_mask) == 2) {
numfilter++;
} else if (sscanf(ptr, "%lx~%lx",
(long unsigned int *)
&rfilter[numfilter].can_id,
(long unsigned int *)
&rfilter[numfilter].can_mask) == 2) {
rfilter[numfilter].can_id |= CAN_INV_FILTER;
numfilter++;
} else if (sscanf(ptr, "#%lx",
(long unsigned int *)&err_mask) != 1) {
printf("Error in filter option parsing: '%s'\n", ptr);
exit(1);
}
if (numfilter > MAXFILTER) {
printf("Too many filters specified for '%s'.\n",
ifr.ifr_name);
exit(1);
}
}
if (err_mask)
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_ERR_FILTER,
&err_mask, sizeof(err_mask));
if (numfilter)
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FILTER,
&rfilter, numfilter * sizeof(struct can_filter));
} /* if (nptr) */
if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind");
return 1;
}
} }
if (nptr) if (log) {
nbytes = nptr - ptr; /* interface name is up the first ',' */ time_t currtime;
else struct tm now;
nbytes = strlen(ptr); /* no ',' found => no filter definitions */ char fname[sizeof("candump-2006-11-20_202026.log")+1];
if (nbytes >= IFNAMSIZ) { if (time(&currtime) == (time_t)-1) {
printf("name of CAN device '%s' is too long!\n", ptr); perror("time");
return 1; return 1;
}
if (nbytes > max_devname_len)
max_devname_len = nbytes; /* for nice printing */
addr.can_family = AF_CAN;
memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
strncpy(ifr.ifr_name, ptr, nbytes);
#ifdef DEBUG
printf("using interface name '%s'.\n", ifr.ifr_name);
#endif
if (strcmp(ANYDEV, ifr.ifr_name)) {
if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX");
exit(1);
}
addr.can_ifindex = ifr.ifr_ifindex;
} else
addr.can_ifindex = 0; /* any can interface */
if (nptr) {
/* found a ',' after the interface name => check for filters */
numfilter = 0;
err_mask = 0;
while (nptr) {
ptr = nptr+1; /* hop behind the ',' */
nptr = strchr(ptr, ','); /* update exit condition */
if (sscanf(ptr, "%lx:%lx",
(long unsigned int *)
&rfilter[numfilter].can_id,
(long unsigned int *)
&rfilter[numfilter].can_mask) == 2) {
numfilter++;
} else if (sscanf(ptr, "%lx~%lx",
(long unsigned int *)
&rfilter[numfilter].can_id,
(long unsigned int *)
&rfilter[numfilter].can_mask) == 2) {
rfilter[numfilter].can_id |= CAN_INV_FILTER;
numfilter++;
} else if (sscanf(ptr, "#%lx",
(long unsigned int *)&err_mask) != 1) {
printf("Error in filter option parsing: '%s'\n", ptr);
exit(1);
} }
if (numfilter > MAXFILTER) { localtime_r(&currtime, &now);
printf("Too many filters specified for '%s'.\n",
ifr.ifr_name); sprintf(fname, "candump-%04d-%02d-%02d_%02d%02d%02d.log",
exit(1); now.tm_year + 1900,
now.tm_mon + 1,
now.tm_mday,
now.tm_hour,
now.tm_min,
now.tm_sec);
printf("\nEnabling Logfile '%s'\n\n", fname);
logfile = fopen(fname, "w");
if (!logfile) {
perror("logfile");
return 1;
} }
}
if (err_mask)
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_ERR_FILTER,
&err_mask, sizeof(err_mask));
if (numfilter)
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FILTER,
&rfilter, numfilter * sizeof(struct can_filter));
} /* if (nptr) */
if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind");
return 1;
}
}
if (log) {
time_t currtime;
struct tm now;
char fname[sizeof("candump-2006-11-20_202026.log")+1];
if (time(&currtime) == (time_t)-1) {
perror("time");
return 1;
} }
localtime_r(&currtime, &now); while (running) {
sprintf(fname, "candump-%04d-%02d-%02d_%02d%02d%02d.log", FD_ZERO(&rdfs);
now.tm_year + 1900, for (i=0; i<currmax; i++)
now.tm_mon + 1, FD_SET(s[i], &rdfs);
now.tm_mday,
now.tm_hour,
now.tm_min,
now.tm_sec);
printf("\nEnabling Logfile '%s'\n\n", fname); if ((ret = select(s[currmax-1]+1, &rdfs, NULL, NULL, NULL)) < 0) {
//perror("select");
running = 0;
continue;
}
logfile = fopen(fname, "w"); for (i=0; i<currmax; i++) { /* check all CAN RAW sockets */
if (!logfile) {
perror("logfile"); if (FD_ISSET(s[i], &rdfs)) {
return 1;
socklen_t len = sizeof(addr);
int idx;
nbytes = recvfrom(s[i], &frame, sizeof(struct can_frame), 0,
(struct sockaddr*)&addr, &len);
if (nbytes < 0) {
perror("read");
return 1;
}
if (nbytes < sizeof(struct can_frame)) {
fprintf(stderr, "read: incomplete CAN frame\n");
return 1;
}
if (bridge) {
nbytes = write(bridge, &frame, sizeof(struct can_frame));
if (nbytes < 0) {
perror("bridge write");
return 1;
} else if (nbytes < sizeof(struct can_frame)) {
fprintf(stderr,"bridge write: incomplete CAN frame\n");
return 1;
}
}
if (timestamp || log || logfrmt)
if (ioctl(s[i], SIOCGSTAMP, &tv) < 0)
perror("SIOCGSTAMP");
idx = idx2dindex(addr.can_ifindex, s[i]);
if (log) {
/* log CAN frame with absolute timestamp & device */
fprintf(logfile, "(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
fprintf(logfile, "%*s ", max_devname_len, devname[idx]);
/* without seperator as logfile use-case is parsing */
fprint_canframe(logfile, &frame, "\n", 0);
}
if (logfrmt) {
/* print CAN frame in log file style to stdout */
printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
printf("%*s ", max_devname_len, devname[idx]);
fprint_canframe(stdout, &frame, "\n", 0);
goto out_fflush; /* no other output to stdout */
}
if (silent){
if (silent == 1) {
printf("%c\b", anichar[silentani%=MAXANI]);
silentani++;
}
goto out_fflush; /* no other output to stdout */
}
printf(" %s", (color>2)?col_on[idx%MAXCOL]:"");
switch (timestamp) {
case 'a': /* absolute with timestamp */
printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
break;
case 'A': /* absolute with date */
{
struct tm tm;
char timestring[25];
tm = *localtime(&tv.tv_sec);
strftime(timestring, 24, "%Y-%m-%d %H:%M:%S", &tm);
printf("(%s.%06ld) ", timestring, tv.tv_usec);
}
break;
case 'd': /* delta */
case 'z': /* starting with zero */
{
struct timeval diff;
if (last_tv.tv_sec == 0) /* first init */
last_tv = tv;
diff.tv_sec = tv.tv_sec - last_tv.tv_sec;
diff.tv_usec = tv.tv_usec - last_tv.tv_usec;
if (diff.tv_usec < 0)
diff.tv_sec--, diff.tv_usec += 1000000;
if (diff.tv_sec < 0)
diff.tv_sec = diff.tv_usec = 0;
printf("(%ld.%06ld) ", diff.tv_sec, diff.tv_usec);
if (timestamp == 'd')
last_tv = tv; /* update for delta calculation */
}
break;
default: /* no timestamp output */
break;
}
printf(" %s", (color && (color<3))?col_on[idx%MAXCOL]:"");
printf("%*s", max_devname_len, devname[idx]);
printf("%s ", (color==1)?col_off:"");
fprint_long_canframe(stdout, &frame, NULL, view);
printf("%s", (color>1)?col_off:"");
printf("\n");
}
out_fflush:
fflush(stdout);
}
} }
}
while (running) {
FD_ZERO(&rdfs);
for (i=0; i<currmax; i++) for (i=0; i<currmax; i++)
FD_SET(s[i], &rdfs); close(s[i]);
if ((ret = select(s[currmax-1]+1, &rdfs, NULL, NULL, NULL)) < 0) { if (bridge)
//perror("select"); close(bridge);
running = 0;
continue;
}
for (i=0; i<currmax; i++) { /* check all CAN RAW sockets */ if (log)
fclose(logfile);
if (FD_ISSET(s[i], &rdfs)) { return 0;
socklen_t len = sizeof(addr);
int idx;
nbytes = recvfrom(s[i], &frame, sizeof(struct can_frame), 0,
(struct sockaddr*)&addr, &len);
if (nbytes < 0) {
perror("read");
return 1;
}
if (nbytes < sizeof(struct can_frame)) {
fprintf(stderr, "read: incomplete CAN frame\n");
return 1;
}
if (bridge) {
nbytes = write(bridge, &frame, sizeof(struct can_frame));
if (nbytes < 0) {
perror("bridge write");
return 1;
} else if (nbytes < sizeof(struct can_frame)) {
fprintf(stderr,"bridge write: incomplete CAN frame\n");
return 1;
}
}
if (timestamp || log || logfrmt)
if (ioctl(s[i], SIOCGSTAMP, &tv) < 0)
perror("SIOCGSTAMP");
idx = idx2dindex(addr.can_ifindex, s[i]);
if (log) {
/* log CAN frame with absolute timestamp & device */
fprintf(logfile, "(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
fprintf(logfile, "%*s ", max_devname_len, devname[idx]);
/* without seperator as logfile use-case is parsing */
fprint_canframe(logfile, &frame, "\n", 0);
}
if (logfrmt) {
/* print CAN frame in log file style to stdout */
printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
printf("%*s ", max_devname_len, devname[idx]);
fprint_canframe(stdout, &frame, "\n", 0);
goto out_fflush; /* no other output to stdout */
}
if (silent){
if (silent == 1) {
printf("%c\b", anichar[silentani%=MAXANI]);
silentani++;
}
goto out_fflush; /* no other output to stdout */
}
printf(" %s", (color>2)?col_on[idx%MAXCOL]:"");
switch (timestamp) {
case 'a': /* absolute with timestamp */
printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
break;
case 'A': /* absolute with date */
{
struct tm tm;
char timestring[25];
tm = *localtime(&tv.tv_sec);
strftime(timestring, 24, "%Y-%m-%d %H:%M:%S", &tm);
printf("(%s.%06ld) ", timestring, tv.tv_usec);
}
break;
case 'd': /* delta */
case 'z': /* starting with zero */
{
struct timeval diff;
if (last_tv.tv_sec == 0) /* first init */
last_tv = tv;
diff.tv_sec = tv.tv_sec - last_tv.tv_sec;
diff.tv_usec = tv.tv_usec - last_tv.tv_usec;
if (diff.tv_usec < 0)
diff.tv_sec--, diff.tv_usec += 1000000;
if (diff.tv_sec < 0)
diff.tv_sec = diff.tv_usec = 0;
printf("(%ld.%06ld) ", diff.tv_sec, diff.tv_usec);
if (timestamp == 'd')
last_tv = tv; /* update for delta calculation */
}
break;
default: /* no timestamp output */
break;
}
printf(" %s", (color && (color<3))?col_on[idx%MAXCOL]:"");
printf("%*s", max_devname_len, devname[idx]);
printf("%s ", (color==1)?col_off:"");
fprint_long_canframe(stdout, &frame, NULL, view);
printf("%s", (color>1)?col_off:"");
printf("\n");
}
out_fflush:
fflush(stdout);
}
}
for (i=0; i<currmax; i++)
close(s[i]);
if (bridge)
close(bridge);
if (log)
fclose(logfile);
return 0;
} }

500
cangen.c
View File

@ -80,306 +80,306 @@ static unsigned long long enobufs_count;
void print_usage(char *prg) void print_usage(char *prg)
{ {
fprintf(stderr, "\n%s: generate CAN frames\n\n", prg); fprintf(stderr, "\n%s: generate CAN frames\n\n", prg);
fprintf(stderr, "Usage: %s [options] <CAN interface>\n", prg); fprintf(stderr, "Usage: %s [options] <CAN interface>\n", prg);
fprintf(stderr, "Options: -g <ms> (gap in milli seconds " fprintf(stderr, "Options: -g <ms> (gap in milli seconds "
"- default: %d ms)\n", DEFAULT_GAP); "- default: %d ms)\n", DEFAULT_GAP);
fprintf(stderr, " -e (generate extended frame mode " fprintf(stderr, " -e (generate extended frame mode "
"(EFF) CAN frames)\n"); "(EFF) CAN frames)\n");
fprintf(stderr, " -I <mode> (CAN ID" fprintf(stderr, " -I <mode> (CAN ID"
" generation mode - see below)\n"); " generation mode - see below)\n");
fprintf(stderr, " -L <mode> (CAN data length code (dlc)" fprintf(stderr, " -L <mode> (CAN data length code (dlc)"
" generation mode - see below)\n"); " generation mode - see below)\n");
fprintf(stderr, " -D <mode> (CAN data (payload)" fprintf(stderr, " -D <mode> (CAN data (payload)"
" generation mode - see below)\n"); " generation mode - see below)\n");
fprintf(stderr, " -i (ignore -ENOBUFS return values on" fprintf(stderr, " -i (ignore -ENOBUFS return values on"
" write() syscalls)\n"); " write() syscalls)\n");
fprintf(stderr, " -x (disable local loopback of " fprintf(stderr, " -x (disable local loopback of "
"generated CAN frames)\n"); "generated CAN frames)\n");
fprintf(stderr, " -v (increment verbose level for " fprintf(stderr, " -v (increment verbose level for "
"printing sent CAN frames)\n\n"); "printing sent CAN frames)\n\n");
fprintf(stderr, "Generation modes:\n"); fprintf(stderr, "Generation modes:\n");
fprintf(stderr, "'r' => random values (default)\n"); fprintf(stderr, "'r' => random values (default)\n");
fprintf(stderr, "'i' => increment values\n"); fprintf(stderr, "'i' => increment values\n");
fprintf(stderr, "<hexvalue> => fix value using <hexvalue>\n\n"); fprintf(stderr, "<hexvalue> => fix value using <hexvalue>\n\n");
fprintf(stderr, "When incrementing the CAN data the data length code " fprintf(stderr, "When incrementing the CAN data the data length code "
"minimum is set to 1.\n"); "minimum is set to 1.\n");
fprintf(stderr, "CAN IDs and data content are given and expected in hexadecimal values.\n\n"); fprintf(stderr, "CAN IDs and data content are given and expected in hexadecimal values.\n\n");
fprintf(stderr, "Examples:\n"); fprintf(stderr, "Examples:\n");
fprintf(stderr, "%s vcan0 -g 4 -I 42A -L 1 -D i -v -v ", prg); fprintf(stderr, "%s vcan0 -g 4 -I 42A -L 1 -D i -v -v ", prg);
fprintf(stderr, "(fixed CAN ID and length, inc. data)\n"); fprintf(stderr, "(fixed CAN ID and length, inc. data)\n");
fprintf(stderr, "%s vcan0 -e -L i -v -v -v ", prg); fprintf(stderr, "%s vcan0 -e -L i -v -v -v ", prg);
fprintf(stderr, "(generate EFF frames, incr. length)\n"); fprintf(stderr, "(generate EFF frames, incr. length)\n");
fprintf(stderr, "%s vcan0 -D 11223344DEADBEEF -L 8 ", prg); fprintf(stderr, "%s vcan0 -D 11223344DEADBEEF -L 8 ", prg);
fprintf(stderr, "(fixed CAN data payload and length)\n"); fprintf(stderr, "(fixed CAN data payload and length)\n");
fprintf(stderr, "%s vcan0 -g 0 -i -x ", prg); fprintf(stderr, "%s vcan0 -g 0 -i -x ", prg);
fprintf(stderr, "(full load test ignoring -ENOBUFS)\n"); fprintf(stderr, "(full load test ignoring -ENOBUFS)\n");
fprintf(stderr, "%s vcan0 ", prg); fprintf(stderr, "%s vcan0 ", prg);
fprintf(stderr, "(my favourite default :)\n\n"); fprintf(stderr, "(my favourite default :)\n\n");
} }
void sigterm(int signo) void sigterm(int signo)
{ {
running = 0; running = 0;
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
unsigned long gap = DEFAULT_GAP; unsigned long gap = DEFAULT_GAP;
unsigned char ignore_enobufs = 0; unsigned char ignore_enobufs = 0;
unsigned char extended = 0; unsigned char extended = 0;
unsigned char id_mode = MODE_RANDOM; unsigned char id_mode = MODE_RANDOM;
unsigned char data_mode = MODE_RANDOM; unsigned char data_mode = MODE_RANDOM;
unsigned char dlc_mode = MODE_RANDOM; unsigned char dlc_mode = MODE_RANDOM;
unsigned char loopback_disable = 0; unsigned char loopback_disable = 0;
unsigned char verbose = 0; unsigned char verbose = 0;
uint64_t incdata = 0; uint64_t incdata = 0;
int opt; int opt;
int s; /* socket */ int s; /* socket */
struct sockaddr_can addr; struct sockaddr_can addr;
static struct can_frame frame; static struct can_frame frame;
int nbytes; int nbytes;
int i; int i;
struct ifreq ifr; struct ifreq ifr;
struct timespec ts; struct timespec ts;
signal(SIGTERM, sigterm); signal(SIGTERM, sigterm);
signal(SIGHUP, sigterm); signal(SIGHUP, sigterm);
signal(SIGINT, sigterm); signal(SIGINT, sigterm);
while ((opt = getopt(argc, argv, "ig:eI:L:D:xvh?")) != -1) { while ((opt = getopt(argc, argv, "ig:eI:L:D:xvh?")) != -1) {
switch (opt) { switch (opt) {
case 'i': case 'i':
ignore_enobufs = 1; ignore_enobufs = 1;
break; break;
case 'g': case 'g':
gap = strtoul(optarg, NULL, 10); gap = strtoul(optarg, NULL, 10);
break; break;
case 'e': case 'e':
extended = 1; extended = 1;
break; break;
case 'I': case 'I':
if (optarg[0] == 'r') { if (optarg[0] == 'r') {
id_mode = MODE_RANDOM; id_mode = MODE_RANDOM;
} else if (optarg[0] == 'i') { } else if (optarg[0] == 'i') {
id_mode = MODE_INCREMENT; id_mode = MODE_INCREMENT;
} else { } else {
id_mode = MODE_FIX; id_mode = MODE_FIX;
frame.can_id = strtoul(optarg, NULL, 16); frame.can_id = strtoul(optarg, NULL, 16);
} }
break; break;
case 'L': case 'L':
if (optarg[0] == 'r') { if (optarg[0] == 'r') {
dlc_mode = MODE_RANDOM; dlc_mode = MODE_RANDOM;
} else if (optarg[0] == 'i') { } else if (optarg[0] == 'i') {
dlc_mode = MODE_INCREMENT; dlc_mode = MODE_INCREMENT;
} else { } else {
dlc_mode = MODE_FIX; dlc_mode = MODE_FIX;
frame.can_dlc = atoi(optarg)%9; frame.can_dlc = atoi(optarg)%9;
} }
break; break;
case 'D': case 'D':
if (optarg[0] == 'r') { if (optarg[0] == 'r') {
data_mode = MODE_RANDOM; data_mode = MODE_RANDOM;
} else if (optarg[0] == 'i') { } else if (optarg[0] == 'i') {
data_mode = MODE_INCREMENT; data_mode = MODE_INCREMENT;
} else { } else {
data_mode = MODE_FIX; data_mode = MODE_FIX;
incdata = strtoull(optarg, NULL, 16); incdata = strtoull(optarg, NULL, 16);
for (i=0; i<8 ;i++) for (i=0; i<8 ;i++)
frame.data[i] = (incdata >> (7-i)*8) & 0xFFULL; frame.data[i] = (incdata >> (7-i)*8) & 0xFFULL;
} }
break; break;
case 'v': case 'v':
verbose++; verbose++;
break; break;
case 'x': case 'x':
loopback_disable = 1; loopback_disable = 1;
break; break;
case '?': case '?':
case 'h': case 'h':
default: default:
print_usage(basename(argv[0])); print_usage(basename(argv[0]));
return 1; return 1;
break; break;
}
} }
}
if (optind == argc) { if (optind == argc) {
print_usage(basename(argv[0])); print_usage(basename(argv[0]));
return 1; return 1;
} }
ts.tv_sec = gap / 1000; ts.tv_sec = gap / 1000;
ts.tv_nsec = (gap % 1000) * 1000000; ts.tv_nsec = (gap % 1000) * 1000000;
if (id_mode == MODE_FIX) { if (id_mode == MODE_FIX) {
/* recognize obviously missing commandline option */ /* recognize obviously missing commandline option */
if ((frame.can_id > 0x7FF) && !extended) { if ((frame.can_id > 0x7FF) && !extended) {
printf("The given CAN-ID is greater than 0x7FF and " printf("The given CAN-ID is greater than 0x7FF and "
"the '-e' option is not set.\n"); "the '-e' option is not set.\n");
return 1; return 1;
}
if (extended)
frame.can_id &= CAN_EFF_MASK;
else
frame.can_id &= CAN_SFF_MASK;
} }
if (extended) if (extended)
frame.can_id &= CAN_EFF_MASK; frame.can_id |= CAN_EFF_FLAG;
else
frame.can_id &= CAN_SFF_MASK;
}
if (extended) if ((data_mode == MODE_INCREMENT) && !frame.can_dlc)
frame.can_id |= CAN_EFF_FLAG;
if ((data_mode == MODE_INCREMENT) && !frame.can_dlc)
frame.can_dlc = 1; /* min dlc value for incr. data */
if (strlen(argv[optind]) >= IFNAMSIZ) {
printf("Name of CAN device '%s' is too long!\n\n", argv[optind]);
return 1;
}
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
perror("socket");
return 1;
}
addr.can_family = AF_CAN;
strcpy(ifr.ifr_name, argv[optind]);
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX");
return 1;
}
addr.can_ifindex = ifr.ifr_ifindex;
/* disable default receive filter on this RAW socket */
/* This is obsolete as we do not read from the socket at all, but for */
/* this reason we can remove the receive list in the Kernel to save a */
/* little (really a very little!) CPU usage. */
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
if (loopback_disable) {
int loopback = 0;
setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
&loopback, sizeof(loopback));
}
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind");
return 1;
}
while (running) {
if (id_mode == MODE_RANDOM) {
frame.can_id = random();
if (extended) {
frame.can_id &= CAN_EFF_MASK;
frame.can_id |= CAN_EFF_FLAG;
} else
frame.can_id &= CAN_SFF_MASK;
}
if (dlc_mode == MODE_RANDOM) {
frame.can_dlc = random() & 0xF;
if (frame.can_dlc & 8)
frame.can_dlc = 8; /* for about 50% of the frames */
if ((data_mode == MODE_INCREMENT) && !frame.can_dlc)
frame.can_dlc = 1; /* min dlc value for incr. data */ frame.can_dlc = 1; /* min dlc value for incr. data */
}
if (data_mode == MODE_RANDOM) { if (strlen(argv[optind]) >= IFNAMSIZ) {
printf("Name of CAN device '%s' is too long!\n\n", argv[optind]);
/* that's what the 64 bit alignment of data[] is for ... :) */
*(unsigned long*)(&frame.data[0]) = random();
*(unsigned long*)(&frame.data[4]) = random();
}
if (verbose) {
printf(" %s ", argv[optind]);
if (verbose > 1)
fprint_long_canframe(stdout, &frame, "\n", (verbose > 2)?1:0);
else
fprint_canframe(stdout, &frame, "\n", 1);
}
nbytes = write(s, &frame, sizeof(struct can_frame));
if (nbytes < 0) {
if (errno != ENOBUFS) {
perror("write");
return 1; return 1;
} }
if (!ignore_enobufs) {
perror("write"); if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
perror("socket");
return 1; return 1;
}
enobufs_count++;
} else if (nbytes < sizeof(struct can_frame)) {
fprintf(stderr, "write: incomplete CAN frame\n");
return 1;
} }
if (gap) /* gap == 0 => performance test :-] */ addr.can_family = AF_CAN;
if (nanosleep(&ts, NULL))
strcpy(ifr.ifr_name, argv[optind]);
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX");
return 1; return 1;
}
addr.can_ifindex = ifr.ifr_ifindex;
if (id_mode == MODE_INCREMENT) { /* disable default receive filter on this RAW socket */
/* This is obsolete as we do not read from the socket at all, but for */
/* this reason we can remove the receive list in the Kernel to save a */
/* little (really a very little!) CPU usage. */
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
frame.can_id++; if (loopback_disable) {
int loopback = 0;
if (extended) { setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
frame.can_id &= CAN_EFF_MASK; &loopback, sizeof(loopback));
frame.can_id |= CAN_EFF_FLAG;
} else
frame.can_id &= CAN_SFF_MASK;
} }
if (dlc_mode == MODE_INCREMENT) { if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind");
frame.can_dlc++; return 1;
frame.can_dlc %= 9;
if ((data_mode == MODE_INCREMENT) && !frame.can_dlc)
frame.can_dlc = 1; /* min dlc value for incr. data */
} }
if (data_mode == MODE_INCREMENT) { while (running) {
incdata++; if (id_mode == MODE_RANDOM) {
for (i=0; i<8 ;i++) frame.can_id = random();
frame.data[i] = (incdata >> i*8) & 0xFFULL;
if (extended) {
frame.can_id &= CAN_EFF_MASK;
frame.can_id |= CAN_EFF_FLAG;
} else
frame.can_id &= CAN_SFF_MASK;
}
if (dlc_mode == MODE_RANDOM) {
frame.can_dlc = random() & 0xF;
if (frame.can_dlc & 8)
frame.can_dlc = 8; /* for about 50% of the frames */
if ((data_mode == MODE_INCREMENT) && !frame.can_dlc)
frame.can_dlc = 1; /* min dlc value for incr. data */
}
if (data_mode == MODE_RANDOM) {
/* that's what the 64 bit alignment of data[] is for ... :) */
*(unsigned long*)(&frame.data[0]) = random();
*(unsigned long*)(&frame.data[4]) = random();
}
if (verbose) {
printf(" %s ", argv[optind]);
if (verbose > 1)
fprint_long_canframe(stdout, &frame, "\n", (verbose > 2)?1:0);
else
fprint_canframe(stdout, &frame, "\n", 1);
}
nbytes = write(s, &frame, sizeof(struct can_frame));
if (nbytes < 0) {
if (errno != ENOBUFS) {
perror("write");
return 1;
}
if (!ignore_enobufs) {
perror("write");
return 1;
}
enobufs_count++;
} else if (nbytes < sizeof(struct can_frame)) {
fprintf(stderr, "write: incomplete CAN frame\n");
return 1;
}
if (gap) /* gap == 0 => performance test :-] */
if (nanosleep(&ts, NULL))
return 1;
if (id_mode == MODE_INCREMENT) {
frame.can_id++;
if (extended) {
frame.can_id &= CAN_EFF_MASK;
frame.can_id |= CAN_EFF_FLAG;
} else
frame.can_id &= CAN_SFF_MASK;
}
if (dlc_mode == MODE_INCREMENT) {
frame.can_dlc++;
frame.can_dlc %= 9;
if ((data_mode == MODE_INCREMENT) && !frame.can_dlc)
frame.can_dlc = 1; /* min dlc value for incr. data */
}
if (data_mode == MODE_INCREMENT) {
incdata++;
for (i=0; i<8 ;i++)
frame.data[i] = (incdata >> i*8) & 0xFFULL;
}
} }
}
if (enobufs_count) if (enobufs_count)
printf("\nCounted %llu ENOBUFS return values on write().\n\n", printf("\nCounted %llu ENOBUFS return values on write().\n\n",
enobufs_count); enobufs_count);
close(s); close(s);
return 0; return 0;
} }

View File

@ -86,68 +86,68 @@ static volatile int running = 1;
void print_usage(char *prg) void print_usage(char *prg)
{ {
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg); fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg); fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg);
fprintf(stderr, "Options: -m <mask> (ID filter mask. Default 0x00000000) *\n"); fprintf(stderr, "Options: -m <mask> (ID filter mask. Default 0x00000000) *\n");
fprintf(stderr, " -v <value> (ID filter value. Default 0x00000000) *\n"); fprintf(stderr, " -v <value> (ID filter value. Default 0x00000000) *\n");
fprintf(stderr, " -i <0|1> (invert the specified ID filter) *\n"); fprintf(stderr, " -i <0|1> (invert the specified ID filter) *\n");
fprintf(stderr, " -e <emask> (mask for error frames)\n"); fprintf(stderr, " -e <emask> (mask for error frames)\n");
fprintf(stderr, " -p <port> (listen on port <port>. Default: %d)\n", DEFPORT); fprintf(stderr, " -p <port> (listen on port <port>. Default: %d)\n", DEFPORT);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "* The CAN ID filter matches, when ...\n"); fprintf(stderr, "* The CAN ID filter matches, when ...\n");
fprintf(stderr, " <received_can_id> & mask == value & mask\n"); fprintf(stderr, " <received_can_id> & mask == value & mask\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "When using more than one CAN interface the options\n"); fprintf(stderr, "When using more than one CAN interface the options\n");
fprintf(stderr, "m/v/i/e have comma seperated values e.g. '-m 0,7FF,0'\n"); fprintf(stderr, "m/v/i/e have comma seperated values e.g. '-m 0,7FF,0'\n");
fprintf(stderr, "\nUse interface name '%s' to receive from all CAN interfaces.\n\n", ANYDEV); fprintf(stderr, "\nUse interface name '%s' to receive from all CAN interfaces.\n\n", ANYDEV);
} }
int idx2dindex(int ifidx, int socket) int idx2dindex(int ifidx, int socket)
{ {
int i; int i;
struct ifreq ifr; struct ifreq ifr;
for (i=0; i<MAXDEV; i++) { for (i=0; i<MAXDEV; i++) {
if (dindex[i] == ifidx) if (dindex[i] == ifidx)
return i; return i;
}
/* create new interface index cache entry */
/* remove index cache zombies first */
for (i=0; i < MAXDEV; i++) {
if (dindex[i]) {
ifr.ifr_ifindex = dindex[i];
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
dindex[i] = 0;
} }
}
for (i=0; i < MAXDEV; i++) /* create new interface index cache entry */
if (!dindex[i]) /* free entry */
break;
if (i == MAXDEV) { /* remove index cache zombies first */
printf("Interface index cache only supports %d interfaces.\n", MAXDEV); for (i=0; i < MAXDEV; i++) {
exit(1); if (dindex[i]) {
} ifr.ifr_ifindex = dindex[i];
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
dindex[i] = 0;
}
}
dindex[i] = ifidx; for (i=0; i < MAXDEV; i++)
if (!dindex[i]) /* free entry */
break;
ifr.ifr_ifindex = ifidx; if (i == MAXDEV) {
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0) printf("Interface index cache only supports %d interfaces.\n", MAXDEV);
perror("SIOCGIFNAME"); exit(1);
}
if (max_devname_len < strlen(ifr.ifr_name)) dindex[i] = ifidx;
max_devname_len = strlen(ifr.ifr_name);
strcpy(devname[i], ifr.ifr_name); ifr.ifr_ifindex = ifidx;
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
perror("SIOCGIFNAME");
if (max_devname_len < strlen(ifr.ifr_name))
max_devname_len = strlen(ifr.ifr_name);
strcpy(devname[i], ifr.ifr_name);
#ifdef DEBUG #ifdef DEBUG
printf("new index %d (%s)\n", i, devname[i]); printf("new index %d (%s)\n", i, devname[i]);
#endif #endif
return i; return i;
} }
/* /*
@ -156,7 +156,7 @@ int idx2dindex(int ifidx, int socket)
*/ */
void childdied(int i) void childdied(int i)
{ {
wait(NULL); wait(NULL);
} }
/* /*
@ -164,273 +164,273 @@ void childdied(int i)
*/ */
void shutdown_gra(int i) void shutdown_gra(int i)
{ {
exit(0); exit(0);
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct sigaction signalaction; struct sigaction signalaction;
sigset_t sigset; sigset_t sigset;
fd_set rdfs; fd_set rdfs;
int s[MAXDEV]; int s[MAXDEV];
int socki, accsocket; int socki, accsocket;
canid_t mask[MAXDEV] = {0}; canid_t mask[MAXDEV] = {0};
canid_t value[MAXDEV] = {0}; canid_t value[MAXDEV] = {0};
int inv_filter[MAXDEV] = {0}; int inv_filter[MAXDEV] = {0};
can_err_mask_t err_mask[MAXDEV] = {0}; can_err_mask_t err_mask[MAXDEV] = {0};
int opt, ret; int opt, ret;
int currmax = 1; /* we assume at least one can bus ;-) */ int currmax = 1; /* we assume at least one can bus ;-) */
struct sockaddr_can addr; struct sockaddr_can addr;
struct can_filter rfilter; struct can_filter rfilter;
struct can_frame frame; struct can_frame frame;
int nbytes, i, j; int nbytes, i, j;
struct ifreq ifr; struct ifreq ifr;
struct timeval tv, last_tv; struct timeval tv, last_tv;
int port = DEFPORT; int port = DEFPORT;
struct sockaddr_in inaddr; struct sockaddr_in inaddr;
struct sockaddr_in clientaddr; struct sockaddr_in clientaddr;
socklen_t sin_size = sizeof(clientaddr); socklen_t sin_size = sizeof(clientaddr);
char temp[128]; char temp[128];
sigemptyset(&sigset); sigemptyset(&sigset);
signalaction.sa_handler = &childdied; signalaction.sa_handler = &childdied;
signalaction.sa_mask = sigset; signalaction.sa_mask = sigset;
signalaction.sa_flags = 0; signalaction.sa_flags = 0;
sigaction(SIGCHLD, &signalaction, NULL); /* install signal for dying child */ sigaction(SIGCHLD, &signalaction, NULL); /* install signal for dying child */
signalaction.sa_handler = &shutdown_gra; signalaction.sa_handler = &shutdown_gra;
signalaction.sa_mask = sigset; signalaction.sa_mask = sigset;
signalaction.sa_flags = 0; signalaction.sa_flags = 0;
sigaction(SIGTERM, &signalaction, NULL); /* install Signal for termination */ sigaction(SIGTERM, &signalaction, NULL); /* install Signal for termination */
sigaction(SIGINT, &signalaction, NULL); /* install Signal for termination */ sigaction(SIGINT, &signalaction, NULL); /* install Signal for termination */
last_tv.tv_sec = 0; last_tv.tv_sec = 0;
last_tv.tv_usec = 0; last_tv.tv_usec = 0;
while ((opt = getopt(argc, argv, "m:v:i:e:p:?")) != -1) { while ((opt = getopt(argc, argv, "m:v:i:e:p:?")) != -1) {
switch (opt) { switch (opt) {
case 'm': case 'm':
i = sscanf(optarg, "%x,%x,%x,%x,%x,%x", i = sscanf(optarg, "%x,%x,%x,%x,%x,%x",
&mask[0], &mask[1], &mask[2], &mask[0], &mask[1], &mask[2],
&mask[3], &mask[4], &mask[5]); &mask[3], &mask[4], &mask[5]);
if (i > currmax) if (i > currmax)
currmax = i; currmax = i;
break; break;
case 'v': case 'v':
i = sscanf(optarg, "%x,%x,%x,%x,%x,%x", i = sscanf(optarg, "%x,%x,%x,%x,%x,%x",
&value[0], &value[1], &value[2], &value[0], &value[1], &value[2],
&value[3], &value[4], &value[5]); &value[3], &value[4], &value[5]);
if (i > currmax) if (i > currmax)
currmax = i; currmax = i;
break; break;
case 'i': case 'i':
i = sscanf(optarg, "%d,%d,%d,%d,%d,%d", i = sscanf(optarg, "%d,%d,%d,%d,%d,%d",
&inv_filter[0], &inv_filter[1], &inv_filter[2], &inv_filter[0], &inv_filter[1], &inv_filter[2],
&inv_filter[3], &inv_filter[4], &inv_filter[5]); &inv_filter[3], &inv_filter[4], &inv_filter[5]);
if (i > currmax) if (i > currmax)
currmax = i; currmax = i;
break; break;
case 'e': case 'e':
i = sscanf(optarg, "%x,%x,%x,%x,%x,%x", i = sscanf(optarg, "%x,%x,%x,%x,%x,%x",
&err_mask[0], &err_mask[1], &err_mask[2], &err_mask[0], &err_mask[1], &err_mask[2],
&err_mask[3], &err_mask[4], &err_mask[5]); &err_mask[3], &err_mask[4], &err_mask[5]);
if (i > currmax) if (i > currmax)
currmax = i; currmax = i;
break; break;
case 'p': case 'p':
port = atoi(optarg); port = atoi(optarg);
break; break;
default: default:
print_usage(basename(argv[0])); print_usage(basename(argv[0]));
exit(1); exit(1);
break; break;
}
} }
}
if (optind == argc) { if (optind == argc) {
print_usage(basename(argv[0])); print_usage(basename(argv[0]));
exit(0); exit(0);
}
/* count in options higher than device count ? */
if (optind + currmax > argc) {
printf("low count of CAN devices!\n");
return 1;
}
currmax = argc - optind; /* find real number of CAN devices */
if (currmax > MAXDEV) {
printf("More than %d CAN devices!\n", MAXDEV);
return 1;
}
socki = socket(PF_INET, SOCK_STREAM, 0);
if (socki < 0) {
perror("socket");
exit(1);
}
inaddr.sin_family = AF_INET;
inaddr.sin_addr.s_addr = htonl(INADDR_ANY);
inaddr.sin_port = htons(port);
while(bind(socki, (struct sockaddr*)&inaddr, sizeof(inaddr)) < 0) {
printf(".");fflush(NULL);
usleep(100000);
}
if (listen(socki, 3) != 0) {
perror("listen");
exit(1);
}
while(1) {
accsocket = accept(socki, (struct sockaddr*)&clientaddr, &sin_size);
if (accsocket > 0) {
//printf("accepted\n");
if (!fork())
break;
else
close(accsocket);
} }
else if (errno != EINTR) {
perror("accept");
exit(1);
}
}
for (i=0; i<currmax; i++) { /* count in options higher than device count ? */
if (optind + currmax > argc) {
printf("low count of CAN devices!\n");
return 1;
}
currmax = argc - optind; /* find real number of CAN devices */
if (currmax > MAXDEV) {
printf("More than %d CAN devices!\n", MAXDEV);
return 1;
}
socki = socket(PF_INET, SOCK_STREAM, 0);
if (socki < 0) {
perror("socket");
exit(1);
}
inaddr.sin_family = AF_INET;
inaddr.sin_addr.s_addr = htonl(INADDR_ANY);
inaddr.sin_port = htons(port);
while(bind(socki, (struct sockaddr*)&inaddr, sizeof(inaddr)) < 0) {
printf(".");fflush(NULL);
usleep(100000);
}
if (listen(socki, 3) != 0) {
perror("listen");
exit(1);
}
while(1) {
accsocket = accept(socki, (struct sockaddr*)&clientaddr, &sin_size);
if (accsocket > 0) {
//printf("accepted\n");
if (!fork())
break;
else
close(accsocket);
}
else if (errno != EINTR) {
perror("accept");
exit(1);
}
}
for (i=0; i<currmax; i++) {
#ifdef DEBUG #ifdef DEBUG
printf("open %d '%s' m%08X v%08X i%d e%d.\n", printf("open %d '%s' m%08X v%08X i%d e%d.\n",
i, argv[optind+i], mask[i], value[i], i, argv[optind+i], mask[i], value[i],
inv_filter[i], err_mask[i]); inv_filter[i], err_mask[i]);
#endif #endif
if ((s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) { if ((s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
perror("socket"); perror("socket");
return 1; return 1;
}
if (mask[i] || value[i]) {
printf("CAN ID filter[%d] for %s set to "
"mask = %08X, value = %08X %s\n",
i, argv[optind+i], mask[i], value[i],
(inv_filter[i]) ? "(inv_filter)" : "");
rfilter.can_id = value[i];
rfilter.can_mask = mask[i];
if (inv_filter[i])
rfilter.can_id |= CAN_INV_FILTER;
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FILTER,
&rfilter, sizeof(rfilter));
}
if (err_mask[i])
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_ERR_FILTER,
&err_mask[i], sizeof(err_mask[i]));
j = strlen(argv[optind+i]);
if (!(j < IFNAMSIZ)) {
printf("name of CAN device '%s' is too long!\n", argv[optind+i]);
return 1;
}
if (j > max_devname_len)
max_devname_len = j; /* for nice printing */
addr.can_family = AF_CAN;
if (strcmp(ANYDEV, argv[optind+i])) {
strcpy(ifr.ifr_name, argv[optind+i]);
if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX");
exit(1);
}
addr.can_ifindex = ifr.ifr_ifindex;
}
else
addr.can_ifindex = 0; /* any can interface */
if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bindcan");
return 1;
}
}
while (running) {
FD_ZERO(&rdfs);
for (i=0; i<currmax; i++)
FD_SET(s[i], &rdfs);
if ((ret = select(s[currmax-1]+1, &rdfs, NULL, NULL, NULL)) < 0) {
//perror("select");
running = 0;
continue;
}
for (i=0; i<currmax; i++) { /* check all CAN RAW sockets */
if (FD_ISSET(s[i], &rdfs)) {
socklen_t len = sizeof(addr);
int idx;
if ((nbytes = recvfrom(s[i], &frame,
sizeof(struct can_frame), 0,
(struct sockaddr*)&addr, &len)) < 0) {
perror("read");
return 1;
} }
if (nbytes < sizeof(struct can_frame)) { if (mask[i] || value[i]) {
fprintf(stderr, "read: incomplete CAN frame\n");
return 1; printf("CAN ID filter[%d] for %s set to "
"mask = %08X, value = %08X %s\n",
i, argv[optind+i], mask[i], value[i],
(inv_filter[i]) ? "(inv_filter)" : "");
rfilter.can_id = value[i];
rfilter.can_mask = mask[i];
if (inv_filter[i])
rfilter.can_id |= CAN_INV_FILTER;
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FILTER,
&rfilter, sizeof(rfilter));
} }
if (ioctl(s[i], SIOCGSTAMP, &tv) < 0) if (err_mask[i])
perror("SIOCGSTAMP"); setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_ERR_FILTER,
&err_mask[i], sizeof(err_mask[i]));
j = strlen(argv[optind+i]);
idx = idx2dindex(addr.can_ifindex, s[i]); if (!(j < IFNAMSIZ)) {
printf("name of CAN device '%s' is too long!\n", argv[optind+i]);
sprintf(temp, "(%ld.%06ld) %*s ", return 1;
tv.tv_sec, tv.tv_usec, max_devname_len, devname[idx]);
sprint_canframe(temp+strlen(temp), &frame, 0);
strcat(temp, "\n");
if (write(accsocket, temp, strlen(temp)) < 0) {
perror("writeaccsock");
return 1;
} }
/* printf("%s\n",temp2); */ if (j > max_devname_len)
max_devname_len = j; /* for nice printing */
addr.can_family = AF_CAN;
if (strcmp(ANYDEV, argv[optind+i])) {
strcpy(ifr.ifr_name, argv[optind+i]);
if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX");
exit(1);
}
addr.can_ifindex = ifr.ifr_ifindex;
}
else
addr.can_ifindex = 0; /* any can interface */
if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bindcan");
return 1;
}
}
while (running) {
FD_ZERO(&rdfs);
for (i=0; i<currmax; i++)
FD_SET(s[i], &rdfs);
if ((ret = select(s[currmax-1]+1, &rdfs, NULL, NULL, NULL)) < 0) {
//perror("select");
running = 0;
continue;
}
for (i=0; i<currmax; i++) { /* check all CAN RAW sockets */
if (FD_ISSET(s[i], &rdfs)) {
socklen_t len = sizeof(addr);
int idx;
if ((nbytes = recvfrom(s[i], &frame,
sizeof(struct can_frame), 0,
(struct sockaddr*)&addr, &len)) < 0) {
perror("read");
return 1;
}
if (nbytes < sizeof(struct can_frame)) {
fprintf(stderr, "read: incomplete CAN frame\n");
return 1;
}
if (ioctl(s[i], SIOCGSTAMP, &tv) < 0)
perror("SIOCGSTAMP");
idx = idx2dindex(addr.can_ifindex, s[i]);
sprintf(temp, "(%ld.%06ld) %*s ",
tv.tv_sec, tv.tv_usec, max_devname_len, devname[idx]);
sprint_canframe(temp+strlen(temp), &frame, 0);
strcat(temp, "\n");
if (write(accsocket, temp, strlen(temp)) < 0) {
perror("writeaccsock");
return 1;
}
/* printf("%s\n",temp2); */
#if 0 #if 0
/* print CAN frame in log file style to stdout */ /* print CAN frame in log file style to stdout */
printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec); printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
printf("%*s ", max_devname_len, devname[idx]); printf("%*s ", max_devname_len, devname[idx]);
fprint_canframe(stdout, &frame, "\n", 0); fprint_canframe(stdout, &frame, "\n", 0);
#endif #endif
} }
}
} }
}
for (i=0; i<currmax; i++) for (i=0; i<currmax; i++)
close(s[i]); close(s[i]);
close(accsocket); close(accsocket);
return 0; return 0;
} }

View File

@ -66,9 +66,9 @@
#define BUFSZ 100 /* for one line in the logfile */ #define BUFSZ 100 /* for one line in the logfile */
struct assignment { struct assignment {
char txif[IFNAMSIZ]; char txif[IFNAMSIZ];
int txifidx; int txifidx;
char rxif[IFNAMSIZ]; char rxif[IFNAMSIZ];
}; };
static struct assignment asgn[CHANNELS]; static struct assignment asgn[CHANNELS];
@ -76,28 +76,28 @@ extern int optind, opterr, optopt;
void print_usage(char *prg) void print_usage(char *prg)
{ {
fprintf(stderr, "\nUsage: %s <options> [interface assignment]*\n\n", prg); fprintf(stderr, "\nUsage: %s <options> [interface assignment]*\n\n", prg);
fprintf(stderr, "Options: -I <infile> (default stdin)\n"); fprintf(stderr, "Options: -I <infile> (default stdin)\n");
fprintf(stderr, " -l <num> " fprintf(stderr, " -l <num> "
"(process input file <num> times)\n" "(process input file <num> times)\n"
" " " "
"(Use 'i' for infinite loop - default: %d)\n", DEFAULT_LOOPS); "(Use 'i' for infinite loop - default: %d)\n", DEFAULT_LOOPS);
fprintf(stderr, " -t (ignore timestamps: " fprintf(stderr, " -t (ignore timestamps: "
"send frames immediately)\n"); "send frames immediately)\n");
fprintf(stderr, " -g <ms> (gap in milli " fprintf(stderr, " -g <ms> (gap in milli "
"seconds - default: %d ms)\n", DEFAULT_GAP); "seconds - default: %d ms)\n", DEFAULT_GAP);
fprintf(stderr, " -s <s> (skip gaps in " fprintf(stderr, " -s <s> (skip gaps in "
"timestamps > 's' seconds)\n"); "timestamps > 's' seconds)\n");
fprintf(stderr, " -x (disable local " fprintf(stderr, " -x (disable local "
"loopback of sent CAN frames)\n"); "loopback of sent CAN frames)\n");
fprintf(stderr, " -v (verbose: print " fprintf(stderr, " -v (verbose: print "
"sent CAN frames)\n\n"); "sent CAN frames)\n\n");
fprintf(stderr, "Interface assignment: 0..n assignments like " fprintf(stderr, "Interface assignment: 0..n assignments like "
"<write-if>=<log-if>\n"); "<write-if>=<log-if>\n");
fprintf(stderr, "e.g. vcan2=can0 ( send frames received from can0 on " fprintf(stderr, "e.g. vcan2=can0 ( send frames received from can0 on "
"vcan2 )\n"); "vcan2 )\n");
fprintf(stderr, "No assignments => send frames to the interface(s) they " fprintf(stderr, "No assignments => send frames to the interface(s) they "
"had been received from.\n\n"); "had been received from.\n\n");
} }
/* copied from /usr/src/linux/include/linux/time.h ... /* copied from /usr/src/linux/include/linux/time.h ...
@ -107,367 +107,367 @@ void print_usage(char *prg)
*/ */
static inline int timeval_compare(struct timeval *lhs, struct timeval *rhs) static inline int timeval_compare(struct timeval *lhs, struct timeval *rhs)
{ {
if (lhs->tv_sec < rhs->tv_sec) if (lhs->tv_sec < rhs->tv_sec)
return -1; return -1;
if (lhs->tv_sec > rhs->tv_sec) if (lhs->tv_sec > rhs->tv_sec)
return 1; return 1;
return lhs->tv_usec - rhs->tv_usec; return lhs->tv_usec - rhs->tv_usec;
} }
static inline void create_diff_tv(struct timeval *today, struct timeval *diff, static inline void create_diff_tv(struct timeval *today, struct timeval *diff,
struct timeval *log) { struct timeval *log) {
/* create diff_tv so that log_tv + diff_tv = today_tv */ /* create diff_tv so that log_tv + diff_tv = today_tv */
diff->tv_sec = today->tv_sec - log->tv_sec; diff->tv_sec = today->tv_sec - log->tv_sec;
diff->tv_usec = today->tv_usec - log->tv_usec; diff->tv_usec = today->tv_usec - log->tv_usec;
} }
static inline int frames_to_send(struct timeval *today, struct timeval *diff, static inline int frames_to_send(struct timeval *today, struct timeval *diff,
struct timeval *log) struct timeval *log)
{ {
/* return value <0 when log + diff < today */ /* return value <0 when log + diff < today */
struct timeval cmp; struct timeval cmp;
cmp.tv_sec = log->tv_sec + diff->tv_sec; cmp.tv_sec = log->tv_sec + diff->tv_sec;
cmp.tv_usec = log->tv_usec + diff->tv_usec; cmp.tv_usec = log->tv_usec + diff->tv_usec;
if (cmp.tv_usec > 1000000) { if (cmp.tv_usec > 1000000) {
cmp.tv_usec -= 1000000; cmp.tv_usec -= 1000000;
cmp.tv_sec++; cmp.tv_sec++;
} }
if (cmp.tv_usec < 0) { if (cmp.tv_usec < 0) {
cmp.tv_usec += 1000000; cmp.tv_usec += 1000000;
cmp.tv_sec--; cmp.tv_sec--;
} }
return timeval_compare(&cmp, today); return timeval_compare(&cmp, today);
} }
int get_txidx(char *logif_name) { int get_txidx(char *logif_name) {
int i; int i;
for (i=0; i<CHANNELS; i++) { for (i=0; i<CHANNELS; i++) {
if (asgn[i].rxif[0] == 0) /* end of table content */ if (asgn[i].rxif[0] == 0) /* end of table content */
break; break;
if (strcmp(asgn[i].rxif, logif_name) == 0) /* found device name */ if (strcmp(asgn[i].rxif, logif_name) == 0) /* found device name */
break; break;
} }
if ((i == CHANNELS) || (asgn[i].rxif[0] == 0)) if ((i == CHANNELS) || (asgn[i].rxif[0] == 0))
return 0; /* not found */ return 0; /* not found */
return asgn[i].txifidx; /* return interface index */ return asgn[i].txifidx; /* return interface index */
} }
char *get_txname(char *logif_name) { char *get_txname(char *logif_name) {
int i; int i;
for (i=0; i<CHANNELS; i++) { for (i=0; i<CHANNELS; i++) {
if (asgn[i].rxif[0] == 0) /* end of table content */ if (asgn[i].rxif[0] == 0) /* end of table content */
break; break;
if (strcmp(asgn[i].rxif, logif_name) == 0) /* found device name */ if (strcmp(asgn[i].rxif, logif_name) == 0) /* found device name */
break; break;
} }
if ((i == CHANNELS) || (asgn[i].rxif[0] == 0)) if ((i == CHANNELS) || (asgn[i].rxif[0] == 0))
return 0; /* not found */ return 0; /* not found */
return asgn[i].txif; /* return interface name */ return asgn[i].txif; /* return interface name */
} }
int add_assignment(char *mode, int socket, char *txname, char *rxname, int add_assignment(char *mode, int socket, char *txname, char *rxname,
int verbose) { int verbose) {
struct ifreq ifr; struct ifreq ifr;
int i; int i;
/* find free entry */ /* find free entry */
for (i=0; i<CHANNELS; i++) { for (i=0; i<CHANNELS; i++) {
if (asgn[i].txif[0] == 0) if (asgn[i].txif[0] == 0)
break; break;
} }
if (i == CHANNELS) { if (i == CHANNELS) {
fprintf(stderr, "Assignment table exceeded!\n"); fprintf(stderr, "Assignment table exceeded!\n");
return 1; return 1;
} }
if (strlen(txname) >= IFNAMSIZ) { if (strlen(txname) >= IFNAMSIZ) {
fprintf(stderr, "write-if interface name '%s' too long!", txname); fprintf(stderr, "write-if interface name '%s' too long!", txname);
return 1; return 1;
} }
strcpy(asgn[i].txif, txname); strcpy(asgn[i].txif, txname);
if (strlen(rxname) >= IFNAMSIZ) { if (strlen(rxname) >= IFNAMSIZ) {
fprintf(stderr, "log-if interface name '%s' too long!", rxname); fprintf(stderr, "log-if interface name '%s' too long!", rxname);
return 1; return 1;
} }
strcpy(asgn[i].rxif, rxname); strcpy(asgn[i].rxif, rxname);
strcpy(ifr.ifr_name, txname); strcpy(ifr.ifr_name, txname);
if (ioctl(socket, SIOCGIFINDEX, &ifr) < 0) { if (ioctl(socket, SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX"); perror("SIOCGIFINDEX");
fprintf(stderr, "write-if interface name '%s' is wrong!\n", txname); fprintf(stderr, "write-if interface name '%s' is wrong!\n", txname);
return 1; return 1;
} }
asgn[i].txifidx = ifr.ifr_ifindex; asgn[i].txifidx = ifr.ifr_ifindex;
if (verbose > 1) /* use -v -v to see this */ if (verbose > 1) /* use -v -v to see this */
printf("added %s assignment: log-if=%s write-if=%s write-if-idx=%d\n", printf("added %s assignment: log-if=%s write-if=%s write-if-idx=%d\n",
mode, asgn[i].rxif, asgn[i].txif, asgn[i].txifidx); mode, asgn[i].rxif, asgn[i].txif, asgn[i].txifidx);
return 0; return 0;
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
static char buf[BUFSZ], device[BUFSZ], ascframe[BUFSZ]; static char buf[BUFSZ], device[BUFSZ], ascframe[BUFSZ];
struct sockaddr_can addr; struct sockaddr_can addr;
static struct can_frame frame; static struct can_frame frame;
static struct timeval today_tv, log_tv, last_log_tv, diff_tv; static struct timeval today_tv, log_tv, last_log_tv, diff_tv;
struct timespec sleep_ts; struct timespec sleep_ts;
int s; /* CAN_RAW socket */ int s; /* CAN_RAW socket */
FILE *infile = stdin; FILE *infile = stdin;
unsigned long gap = DEFAULT_GAP; unsigned long gap = DEFAULT_GAP;
int use_timestamps = 1; int use_timestamps = 1;
static int verbose, opt, delay_loops, skipgap; static int verbose, opt, delay_loops, skipgap;
static int loopback_disable = 0; static int loopback_disable = 0;
static int infinite_loops = 0; static int infinite_loops = 0;
static int loops = DEFAULT_LOOPS; static int loops = DEFAULT_LOOPS;
int assignments; /* assignments defined on the commandline */ int assignments; /* assignments defined on the commandline */
int txidx; /* sendto() interface index */ int txidx; /* sendto() interface index */
int eof, nbytes, i, j; int eof, nbytes, i, j;
while ((opt = getopt(argc, argv, "I:l:tg:s:xv")) != -1) { while ((opt = getopt(argc, argv, "I:l:tg:s:xv")) != -1) {
switch (opt) { switch (opt) {
case 'I': case 'I':
infile = fopen(optarg, "r"); infile = fopen(optarg, "r");
if (!infile) { if (!infile) {
perror("infile"); perror("infile");
return 1; return 1;
} }
break; break;
case 'l': case 'l':
if (optarg[0] == 'i') if (optarg[0] == 'i')
infinite_loops = 1; infinite_loops = 1;
else else
if (!(loops = atoi(optarg))) { if (!(loops = atoi(optarg))) {
fprintf(stderr, "Invalid argument for option -l !\n"); fprintf(stderr, "Invalid argument for option -l !\n");
return 1; return 1;
}
break;
case 't':
use_timestamps = 0;
break;
case 'g':
gap = strtoul(optarg, NULL, 10);
break;
case 's':
skipgap = strtoul(optarg, NULL, 10);
if (skipgap < 1) {
fprintf(stderr, "Invalid argument for option -s !\n");
return 1;
}
break;
case 'x':
loopback_disable = 1;
break;
case 'v':
verbose++;
break;
default:
print_usage(basename(argv[0]));
return 1;
break;
} }
break;
case 't':
use_timestamps = 0;
break;
case 'g':
gap = strtoul(optarg, NULL, 10);
break;
case 's':
skipgap = strtoul(optarg, NULL, 10);
if (skipgap < 1) {
fprintf(stderr, "Invalid argument for option -s !\n");
return 1;
}
break;
case 'x':
loopback_disable = 1;
break;
case 'v':
verbose++;
break;
default:
print_usage(basename(argv[0]));
return 1;
break;
} }
}
assignments = argc - optind; /* find real number of user assignments */ assignments = argc - optind; /* find real number of user assignments */
if (infile == stdin) { /* no jokes with stdin */ if (infile == stdin) { /* no jokes with stdin */
infinite_loops = 0; infinite_loops = 0;
loops = 1; loops = 1;
}
if (verbose > 1) /* use -v -v to see this */
if (infinite_loops)
printf("infinite_loops\n");
else
printf("%d loops\n", loops);
sleep_ts.tv_sec = gap / 1000;
sleep_ts.tv_nsec = (gap % 1000) * 1000000;
/* open socket */
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
perror("socket");
return 1;
}
addr.can_family = AF_CAN;
addr.can_ifindex = 0;
/* disable unneeded default receive filter on this RAW socket */
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
if (loopback_disable) {
int loopback = 0;
setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
&loopback, sizeof(loopback));
}
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind");
return 1;
}
if (assignments) {
/* add & check user assginments from commandline */
for (i=0; i<assignments; i++) {
if (strlen(argv[optind+i]) >= BUFSZ) {
fprintf(stderr, "Assignment too long!\n");
print_usage(basename(argv[0]));
return 1;
}
strcpy(buf, argv[optind+i]);
for (j=0; j<BUFSZ; j++) { /* find '=' in assignment */
if (buf[j] == '=')
break;
}
if (buf[j] != '=') {
fprintf(stderr, "'=' missing in assignment!\n");
print_usage(basename(argv[0]));
return 1;
}
buf[j] = 0; /* cut string in two pieces */
if (add_assignment("user", s, &buf[0], &buf[j+1], verbose))
return 1;
} }
}
while (infinite_loops || loops--) {
if (infile != stdin)
rewind(infile); /* for each loop */
if (verbose > 1) /* use -v -v to see this */ if (verbose > 1) /* use -v -v to see this */
printf (">>>>>>>>> start reading file. remaining loops = %d\n", loops); if (infinite_loops)
printf("infinite_loops\n");
else
printf("%d loops\n", loops);
if (!fgets(buf, BUFSZ-1, infile)) /* read first frame from logfile */ sleep_ts.tv_sec = gap / 1000;
goto out; /* nothing to read */ sleep_ts.tv_nsec = (gap % 1000) * 1000000;
eof = 0; /* open socket */
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
if (sscanf(buf, "(%ld.%ld) %s %s", &log_tv.tv_sec, &log_tv.tv_usec, perror("socket");
device, ascframe) != 4) return 1;
return 1;
if (use_timestamps) { /* throttle sending due to logfile timestamps */
gettimeofday(&today_tv, NULL);
create_diff_tv(&today_tv, &diff_tv, &log_tv);
last_log_tv = log_tv;
} }
while (!eof) { addr.can_family = AF_CAN;
addr.can_ifindex = 0;
while ((!use_timestamps) || /* disable unneeded default receive filter on this RAW socket */
(frames_to_send(&today_tv, &diff_tv, &log_tv) < 0)) { setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
/* log_tv/device/ascframe are valid here */ if (loopback_disable) {
int loopback = 0;
if (strlen(device) >= IFNAMSIZ) { setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
fprintf(stderr, "log interface name '%s' too long!", device); &loopback, sizeof(loopback));
return 1; }
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind");
return 1;
}
if (assignments) {
/* add & check user assginments from commandline */
for (i=0; i<assignments; i++) {
if (strlen(argv[optind+i]) >= BUFSZ) {
fprintf(stderr, "Assignment too long!\n");
print_usage(basename(argv[0]));
return 1;
}
strcpy(buf, argv[optind+i]);
for (j=0; j<BUFSZ; j++) { /* find '=' in assignment */
if (buf[j] == '=')
break;
}
if (buf[j] != '=') {
fprintf(stderr, "'=' missing in assignment!\n");
print_usage(basename(argv[0]));
return 1;
}
buf[j] = 0; /* cut string in two pieces */
if (add_assignment("user", s, &buf[0], &buf[j+1], verbose))
return 1;
} }
}
txidx = get_txidx(device); /* get ifindex for sending the frame */ while (infinite_loops || loops--) {
if ((!txidx) && (!assignments)) { if (infile != stdin)
/* ifindex not found and no user assignments */ rewind(infile); /* for each loop */
/* => assign this device automatically */
if (add_assignment("auto", s, device, device, verbose))
return 1;
txidx = get_txidx(device);
}
if (txidx) { /* only send to valid CAN devices */ if (verbose > 1) /* use -v -v to see this */
printf (">>>>>>>>> start reading file. remaining loops = %d\n", loops);
if (parse_canframe(ascframe, &frame)) { if (!fgets(buf, BUFSZ-1, infile)) /* read first frame from logfile */
fprintf(stderr, "wrong CAN frame format: '%s'!", ascframe); goto out; /* nothing to read */
return 1;
}
addr.can_family = AF_CAN; eof = 0;
addr.can_ifindex = txidx; /* send via this interface */
nbytes = sendto(s, &frame, sizeof(struct can_frame), 0,
(struct sockaddr*)&addr, sizeof(addr));
if (nbytes != sizeof(struct can_frame)) {
perror("sendto");
return 1;
}
if (verbose) {
printf("%s (%s) ", get_txname(device), device);
fprint_long_canframe(stdout, &frame, "\n", 1);
}
}
/* read next frame from logfile */
if (!fgets(buf, BUFSZ-1, infile)) {
eof = 1; /* this file is completely processed */
break;
}
if (sscanf(buf, "(%ld.%ld) %s %s", &log_tv.tv_sec, &log_tv.tv_usec, if (sscanf(buf, "(%ld.%ld) %s %s", &log_tv.tv_sec, &log_tv.tv_usec,
device, ascframe) != 4) device, ascframe) != 4)
return 1; return 1;
if (use_timestamps) { if (use_timestamps) { /* throttle sending due to logfile timestamps */
gettimeofday(&today_tv, NULL);
/* test for logfile timestamps jumping backwards OR */ gettimeofday(&today_tv, NULL);
/* if the user likes to skip long gaps in the timestamps */
if ((last_log_tv.tv_sec > log_tv.tv_sec) ||
(skipgap && abs(last_log_tv.tv_sec - log_tv.tv_sec) > skipgap))
create_diff_tv(&today_tv, &diff_tv, &log_tv); create_diff_tv(&today_tv, &diff_tv, &log_tv);
last_log_tv = log_tv;
last_log_tv = log_tv;
} }
} /* while frames_to_send ... */ while (!eof) {
if (nanosleep(&sleep_ts, NULL)) while ((!use_timestamps) ||
return 1; (frames_to_send(&today_tv, &diff_tv, &log_tv) < 0)) {
delay_loops++; /* private statistics */ /* log_tv/device/ascframe are valid here */
gettimeofday(&today_tv, NULL);
} /* while (!eof) */ if (strlen(device) >= IFNAMSIZ) {
fprintf(stderr, "log interface name '%s' too long!", device);
return 1;
}
} /* while (infinite_loops || loops--) */ txidx = get_txidx(device); /* get ifindex for sending the frame */
out: if ((!txidx) && (!assignments)) {
/* ifindex not found and no user assignments */
/* => assign this device automatically */
if (add_assignment("auto", s, device, device, verbose))
return 1;
txidx = get_txidx(device);
}
close(s); if (txidx) { /* only send to valid CAN devices */
fclose(infile);
if (verbose > 1) /* use -v -v to see this */ if (parse_canframe(ascframe, &frame)) {
printf("%d delay_loops\n", delay_loops); fprintf(stderr, "wrong CAN frame format: '%s'!", ascframe);
return 1;
}
return 0; addr.can_family = AF_CAN;
addr.can_ifindex = txidx; /* send via this interface */
nbytes = sendto(s, &frame, sizeof(struct can_frame), 0,
(struct sockaddr*)&addr, sizeof(addr));
if (nbytes != sizeof(struct can_frame)) {
perror("sendto");
return 1;
}
if (verbose) {
printf("%s (%s) ", get_txname(device), device);
fprint_long_canframe(stdout, &frame, "\n", 1);
}
}
/* read next frame from logfile */
if (!fgets(buf, BUFSZ-1, infile)) {
eof = 1; /* this file is completely processed */
break;
}
if (sscanf(buf, "(%ld.%ld) %s %s", &log_tv.tv_sec, &log_tv.tv_usec,
device, ascframe) != 4)
return 1;
if (use_timestamps) {
gettimeofday(&today_tv, NULL);
/* test for logfile timestamps jumping backwards OR */
/* if the user likes to skip long gaps in the timestamps */
if ((last_log_tv.tv_sec > log_tv.tv_sec) ||
(skipgap && abs(last_log_tv.tv_sec - log_tv.tv_sec) > skipgap))
create_diff_tv(&today_tv, &diff_tv, &log_tv);
last_log_tv = log_tv;
}
} /* while frames_to_send ... */
if (nanosleep(&sleep_ts, NULL))
return 1;
delay_loops++; /* private statistics */
gettimeofday(&today_tv, NULL);
} /* while (!eof) */
} /* while (infinite_loops || loops--) */
out:
close(s);
fclose(infile);
if (verbose > 1) /* use -v -v to see this */
printf("%d delay_loops\n", delay_loops);
return 0;
} }

102
cansend.c
View File

@ -60,66 +60,66 @@
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int s; /* can raw socket */ int s; /* can raw socket */
int nbytes; int nbytes;
struct sockaddr_can addr; struct sockaddr_can addr;
struct can_frame frame; struct can_frame frame;
struct ifreq ifr; struct ifreq ifr;
/* check command line options */ /* check command line options */
if (argc != 3) { if (argc != 3) {
fprintf(stderr, "Usage: %s <device> <can_frame>.\n", argv[0]); fprintf(stderr, "Usage: %s <device> <can_frame>.\n", argv[0]);
return 1; return 1;
} }
/* parse CAN frame */ /* parse CAN frame */
if (parse_canframe(argv[2], &frame)){ if (parse_canframe(argv[2], &frame)){
fprintf(stderr, "\nWrong CAN-frame format!\n\n"); fprintf(stderr, "\nWrong CAN-frame format!\n\n");
fprintf(stderr, "Try: <can_id>#{R|data}\n"); fprintf(stderr, "Try: <can_id>#{R|data}\n");
fprintf(stderr, "can_id can have 3 (SFF) or 8 (EFF) hex chars\n"); fprintf(stderr, "can_id can have 3 (SFF) or 8 (EFF) hex chars\n");
fprintf(stderr, "data has 0 to 8 hex-values that can (optionally)"); fprintf(stderr, "data has 0 to 8 hex-values that can (optionally)");
fprintf(stderr, " be seperated by '.'\n\n"); fprintf(stderr, " be seperated by '.'\n\n");
fprintf(stderr, "e.g. 5A1#11.2233.44556677.88 / 123#DEADBEEF / "); fprintf(stderr, "e.g. 5A1#11.2233.44556677.88 / 123#DEADBEEF / ");
fprintf(stderr, "5AA# /\n 1F334455#1122334455667788 / 123#R "); fprintf(stderr, "5AA# /\n 1F334455#1122334455667788 / 123#R ");
fprintf(stderr, "for remote transmission request.\n\n"); fprintf(stderr, "for remote transmission request.\n\n");
return 1; return 1;
} }
/* open socket */ /* open socket */
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) { if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
perror("socket"); perror("socket");
return 1; return 1;
} }
addr.can_family = AF_CAN; addr.can_family = AF_CAN;
strcpy(ifr.ifr_name, argv[1]); strcpy(ifr.ifr_name, argv[1]);
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX"); perror("SIOCGIFINDEX");
return 1; return 1;
} }
addr.can_ifindex = ifr.ifr_ifindex; addr.can_ifindex = ifr.ifr_ifindex;
/* disable default receive filter on this RAW socket */ /* disable default receive filter on this RAW socket */
/* This is obsolete as we do not read from the socket at all, but for */ /* This is obsolete as we do not read from the socket at all, but for */
/* this reason we can remove the receive list in the Kernel to save a */ /* this reason we can remove the receive list in the Kernel to save a */
/* little (really a very little!) CPU usage. */ /* little (really a very little!) CPU usage. */
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0); setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind"); perror("bind");
return 1; return 1;
} }
/* send frame */ /* send frame */
if ((nbytes = write(s, &frame, sizeof(frame))) != sizeof(frame)) { if ((nbytes = write(s, &frame, sizeof(frame))) != sizeof(frame)) {
perror("write"); perror("write");
return 1; return 1;
} }
//fprint_long_canframe(stdout, &frame, "\n", 0); //fprint_long_canframe(stdout, &frame, "\n", 0);
close(s); close(s);
return 0; return 0;
} }

File diff suppressed because it is too large Load Diff

278
lib.c
View File

@ -61,187 +61,187 @@
static int asc2nibble(char c) { static int asc2nibble(char c) {
if ((c >= '0') && (c <= '9')) if ((c >= '0') && (c <= '9'))
return c - '0'; return c - '0';
if ((c >= 'A') && (c <= 'F')) if ((c >= 'A') && (c <= 'F'))
return c - 'A' + 10; return c - 'A' + 10;
if ((c >= 'a') && (c <= 'f')) if ((c >= 'a') && (c <= 'f'))
return c - 'a' + 10; return c - 'a' + 10;
return 16; /* error */ return 16; /* error */
} }
int parse_canframe(char *cs, struct can_frame *cf) { int parse_canframe(char *cs, struct can_frame *cf) {
/* documentation see lib.h */ /* documentation see lib.h */
int i, idx, dlc, len, tmp; int i, idx, dlc, len, tmp;
len = strlen(cs); len = strlen(cs);
//printf("'%s' len %d\n", cs, len); //printf("'%s' len %d\n", cs, len);
memset(cf, 0, sizeof(*cf)); /* init CAN frame, e.g. DLC = 0 */ memset(cf, 0, sizeof(*cf)); /* init CAN frame, e.g. DLC = 0 */
if (len < 4) if (len < 4)
return 1;
if (!((cs[3] == CANID_DELIM) || (cs[8] == CANID_DELIM)))
return 1;
if (cs[8] == CANID_DELIM) { /* 8 digits */
idx = 9;
for (i=0; i<8; i++){
if ((tmp = asc2nibble(cs[i])) > 0x0F)
return 1; return 1;
cf->can_id |= (tmp << (7-i)*4);
}
if (!(cf->can_id & CAN_ERR_FLAG)) /* 8 digits but no errorframe? */
cf->can_id |= CAN_EFF_FLAG; /* then it is an extended frame */
} else { /* 3 digits */ if (!((cs[3] == CANID_DELIM) || (cs[8] == CANID_DELIM)))
idx = 4;
for (i=0; i<3; i++){
if ((tmp = asc2nibble(cs[i])) > 0x0F)
return 1; return 1;
cf->can_id |= (tmp << (2-i)*4);
}
}
if((cs[idx] == 'R') || (cs[idx] == 'r')){ /* RTR frame */ if (cs[8] == CANID_DELIM) { /* 8 digits */
cf->can_id |= CAN_RTR_FLAG;
idx = 9;
for (i=0; i<8; i++){
if ((tmp = asc2nibble(cs[i])) > 0x0F)
return 1;
cf->can_id |= (tmp << (7-i)*4);
}
if (!(cf->can_id & CAN_ERR_FLAG)) /* 8 digits but no errorframe? */
cf->can_id |= CAN_EFF_FLAG; /* then it is an extended frame */
} else { /* 3 digits */
idx = 4;
for (i=0; i<3; i++){
if ((tmp = asc2nibble(cs[i])) > 0x0F)
return 1;
cf->can_id |= (tmp << (2-i)*4);
}
}
if((cs[idx] == 'R') || (cs[idx] == 'r')){ /* RTR frame */
cf->can_id |= CAN_RTR_FLAG;
return 0;
}
for (i=0, dlc=0; i<8; i++){
if(cs[idx] == DATA_SEPERATOR) /* skip (optional) seperator */
idx++;
if(idx >= len) /* end of string => end of data */
break;
if ((tmp = asc2nibble(cs[idx++])) > 0x0F)
return 1;
cf->data[i] = (tmp << 4);
if ((tmp = asc2nibble(cs[idx++])) > 0x0F)
return 1;
cf->data[i] |= tmp;
dlc++;
}
cf->can_dlc = dlc;
return 0; return 0;
}
for (i=0, dlc=0; i<8; i++){
if(cs[idx] == DATA_SEPERATOR) /* skip (optional) seperator */
idx++;
if(idx >= len) /* end of string => end of data */
break;
if ((tmp = asc2nibble(cs[idx++])) > 0x0F)
return 1;
cf->data[i] = (tmp << 4);
if ((tmp = asc2nibble(cs[idx++])) > 0x0F)
return 1;
cf->data[i] |= tmp;
dlc++;
}
cf->can_dlc = dlc;
return 0;
} }
void fprint_canframe(FILE *stream , struct can_frame *cf, char *eol, int sep) { void fprint_canframe(FILE *stream , struct can_frame *cf, char *eol, int sep) {
/* documentation see lib.h */ /* documentation see lib.h */
char buf[sizeof(MAX_CANFRAME)+1]; /* max length */ char buf[sizeof(MAX_CANFRAME)+1]; /* max length */
sprint_canframe(buf, cf, sep); sprint_canframe(buf, cf, sep);
fprintf(stream, "%s", buf); fprintf(stream, "%s", buf);
if (eol) if (eol)
fprintf(stream, "%s", eol); fprintf(stream, "%s", eol);
} }
void sprint_canframe(char *buf , struct can_frame *cf, int sep) { void sprint_canframe(char *buf , struct can_frame *cf, int sep) {
/* documentation see lib.h */ /* documentation see lib.h */
int i,offset; int i,offset;
if (cf->can_id & CAN_ERR_FLAG) { if (cf->can_id & CAN_ERR_FLAG) {
sprintf(buf, "%08X#", cf->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG)); sprintf(buf, "%08X#", cf->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG));
offset = 9; offset = 9;
} else if (cf->can_id & CAN_EFF_FLAG) { } else if (cf->can_id & CAN_EFF_FLAG) {
sprintf(buf, "%08X#", cf->can_id & CAN_EFF_MASK); sprintf(buf, "%08X#", cf->can_id & CAN_EFF_MASK);
offset = 9; offset = 9;
} else { } else {
sprintf(buf, "%03X#", cf->can_id & CAN_SFF_MASK); sprintf(buf, "%03X#", cf->can_id & CAN_SFF_MASK);
offset = 4; offset = 4;
}
if (cf->can_id & CAN_RTR_FLAG) /* there are no ERR frames with RTR */
sprintf(buf+offset, "R");
else
for (i = 0; i < cf->can_dlc; i++) {
sprintf(buf+offset, "%02X", cf->data[i]);
offset += 2;
if (sep && (i+1 < cf->can_dlc))
sprintf(buf+offset++, ".");
} }
if (cf->can_id & CAN_RTR_FLAG) /* there are no ERR frames with RTR */
sprintf(buf+offset, "R");
else
for (i = 0; i < cf->can_dlc; i++) {
sprintf(buf+offset, "%02X", cf->data[i]);
offset += 2;
if (sep && (i+1 < cf->can_dlc))
sprintf(buf+offset++, ".");
}
} }
void fprint_long_canframe(FILE *stream , struct can_frame *cf, char *eol, int view) { void fprint_long_canframe(FILE *stream , struct can_frame *cf, char *eol, int view) {
/* documentation see lib.h */ /* documentation see lib.h */
char buf[sizeof(MAX_LONG_CANFRAME)+1]; /* max length */ char buf[sizeof(MAX_LONG_CANFRAME)+1]; /* max length */
sprint_long_canframe(buf, cf, view); sprint_long_canframe(buf, cf, view);
fprintf(stream, "%s", buf); fprintf(stream, "%s", buf);
if (eol) if (eol)
fprintf(stream, "%s", eol); fprintf(stream, "%s", eol);
} }
void sprint_long_canframe(char *buf , struct can_frame *cf, int view) { void sprint_long_canframe(char *buf , struct can_frame *cf, int view) {
/* documentation see lib.h */ /* documentation see lib.h */
int i, j, dlen, offset; int i, j, dlen, offset;
if (cf->can_id & CAN_ERR_FLAG) { if (cf->can_id & CAN_ERR_FLAG) {
sprintf(buf, "%8X ", cf->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG)); sprintf(buf, "%8X ", cf->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG));
offset = 10; offset = 10;
} else if (cf->can_id & CAN_EFF_FLAG) { } else if (cf->can_id & CAN_EFF_FLAG) {
sprintf(buf, "%8X ", cf->can_id & CAN_EFF_MASK); sprintf(buf, "%8X ", cf->can_id & CAN_EFF_MASK);
offset = 10; offset = 10;
} else { } else {
sprintf(buf, "%3X ", cf->can_id & CAN_SFF_MASK); sprintf(buf, "%3X ", cf->can_id & CAN_SFF_MASK);
offset = 5; offset = 5;
}
sprintf(buf+offset, "[%d]", cf->can_dlc);
offset += 3;
if (cf->can_id & CAN_RTR_FLAG) { /* there are no ERR frames with RTR */
sprintf(buf+offset, " remote request");
return;
}
if (view & CANLIB_VIEW_BINARY) {
dlen = 9; /* _10101010 */
for (i = 0; i < cf->can_dlc; i++) {
buf[offset++] = ' ';
for (j = 7; j >= 0; j--)
buf[offset++] = (1<<j & cf->data[i])?'1':'0';
} }
buf[offset] = 0; /* terminate string */
} else { sprintf(buf+offset, "[%d]", cf->can_dlc);
dlen = 3; /* _AA */ offset += 3;
for (i = 0; i < cf->can_dlc; i++) {
sprintf(buf+offset, " %02X", cf->data[i]); if (cf->can_id & CAN_RTR_FLAG) { /* there are no ERR frames with RTR */
offset += dlen; sprintf(buf+offset, " remote request");
return;
} }
}
if (cf->can_id & CAN_ERR_FLAG) if (view & CANLIB_VIEW_BINARY) {
sprintf(buf+offset, "%*s", dlen*(8-cf->can_dlc)+13, "ERRORFRAME"); dlen = 9; /* _10101010 */
else if (view & CANLIB_VIEW_ASCII) { for (i = 0; i < cf->can_dlc; i++) {
j = dlen*(8-cf->can_dlc)+4; buf[offset++] = ' ';
sprintf(buf+offset, "%*s", j, "'"); for (j = 7; j >= 0; j--)
offset += j; buf[offset++] = (1<<j & cf->data[i])?'1':'0';
}
buf[offset] = 0; /* terminate string */
} else {
dlen = 3; /* _AA */
for (i = 0; i < cf->can_dlc; i++) {
sprintf(buf+offset, " %02X", cf->data[i]);
offset += dlen;
}
}
for (i = 0; i < cf->can_dlc; i++) if (cf->can_id & CAN_ERR_FLAG)
if ((cf->data[i] > 0x1F) && (cf->data[i] < 0x7F)) sprintf(buf+offset, "%*s", dlen*(8-cf->can_dlc)+13, "ERRORFRAME");
buf[offset++] = cf->data[i]; else if (view & CANLIB_VIEW_ASCII) {
else j = dlen*(8-cf->can_dlc)+4;
buf[offset++] = '.'; sprintf(buf+offset, "%*s", j, "'");
offset += j;
sprintf(buf+offset, "'"); for (i = 0; i < cf->can_dlc; i++)
} if ((cf->data[i] > 0x1F) && (cf->data[i] < 0x7F))
buf[offset++] = cf->data[i];
else
buf[offset++] = '.';
sprintf(buf+offset, "'");
}
} }

224
log2asc.c
View File

@ -60,129 +60,129 @@ extern int optind, opterr, optopt;
void print_usage(char *prg) void print_usage(char *prg)
{ {
fprintf(stderr, "Usage: %s [can-interfaces]\n", prg); fprintf(stderr, "Usage: %s [can-interfaces]\n", prg);
fprintf(stderr, "Options: -I <infile> (default stdin)\n"); fprintf(stderr, "Options: -I <infile> (default stdin)\n");
fprintf(stderr, " -O <outfile> (default stdout)\n"); fprintf(stderr, " -O <outfile> (default stdout)\n");
fprintf(stderr, " -4 (reduce decimal place to 4 digits)\n"); fprintf(stderr, " -4 (reduce decimal place to 4 digits)\n");
fprintf(stderr, " -n (set newline to cr/lf - default lf)\n"); fprintf(stderr, " -n (set newline to cr/lf - default lf)\n");
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
char buf[100], device[100], ascframe[100], id[10]; char buf[100], device[100], ascframe[100], id[10];
struct can_frame cf; struct can_frame cf;
static struct timeval tv, start_tv; static struct timeval tv, start_tv;
FILE *infile = stdin; FILE *infile = stdin;
FILE *outfile = stdout; FILE *outfile = stdout;
static int maxdev, devno, i, crlf, d4, opt; static int maxdev, devno, i, crlf, d4, opt;
while ((opt = getopt(argc, argv, "I:O:4n")) != -1) { while ((opt = getopt(argc, argv, "I:O:4n")) != -1) {
switch (opt) { switch (opt) {
case 'I': case 'I':
infile = fopen(optarg, "r"); infile = fopen(optarg, "r");
if (!infile) { if (!infile) {
perror("infile"); perror("infile");
return 1; return 1;
} }
break; break;
case 'O': case 'O':
outfile = fopen(optarg, "w"); outfile = fopen(optarg, "w");
if (!outfile) { if (!outfile) {
perror("outfile"); perror("outfile");
return 1; return 1;
} }
break; break;
case 'n': case 'n':
crlf = 1; crlf = 1;
break; break;
case '4': case '4':
d4 = 1; d4 = 1;
break; break;
default: default:
fprintf(stderr, "Unknown option %c\n", opt); fprintf(stderr, "Unknown option %c\n", opt);
print_usage(basename(argv[0])); print_usage(basename(argv[0]));
return 1; return 1;
break; break;
}
}
maxdev = argc - optind; /* find real number of CAN devices */
if (!maxdev) {
fprintf(stderr, "no CAN interfaces defined!\n");
print_usage(basename(argv[0]));
return 1;
}
//printf("Found %d CAN devices!\n", maxdev);
while (fgets(buf, 99, infile)) {
if (sscanf(buf, "(%ld.%ld) %s %s", &tv.tv_sec, &tv.tv_usec,
device, ascframe) != 4)
return 1;
if (!start_tv.tv_sec) { /* print banner */
start_tv = tv;
fprintf(outfile, "date %s", ctime(&start_tv.tv_sec));
fprintf(outfile, "base hex timestamps absolute%s",
(crlf)?"\r\n":"\n");
fprintf(outfile, "no internal events logged%s",
(crlf)?"\r\n":"\n");
}
for (i=0, devno=0; i<maxdev; i++) {
if (!strcmp(device, argv[optind+i])) {
devno = i+1; /* start with channel '1' */
break;
}
}
if (devno) { /* only convert for selected CAN devices */
if (parse_canframe(ascframe, &cf))
return 1;
tv.tv_sec = tv.tv_sec - start_tv.tv_sec;
tv.tv_usec = tv.tv_usec - start_tv.tv_usec;
if (tv.tv_usec < 0)
tv.tv_sec--, tv.tv_usec += 1000000;
if (tv.tv_sec < 0)
tv.tv_sec = tv.tv_usec = 0;
if (d4)
fprintf(outfile, "%4ld.%04ld ", tv.tv_sec, tv.tv_usec/100);
else
fprintf(outfile, "%4ld.%06ld ", tv.tv_sec, tv.tv_usec);
fprintf(outfile, "%-2d ", devno); /* channel number left aligned */
if (cf.can_id & CAN_ERR_FLAG)
fprintf(outfile, "ErrorFrame");
else {
sprintf(id, "%X%c", cf.can_id & CAN_EFF_MASK,
(cf.can_id & CAN_EFF_FLAG)?'x':' ');
fprintf(outfile, "%-15s Rx ", id);
if (cf.can_id & CAN_RTR_FLAG)
fprintf(outfile, "r"); /* RTR frame */
else {
fprintf(outfile, "d %d", cf.can_dlc); /* data frame */
for (i = 0; i < cf.can_dlc; i++) {
fprintf(outfile, " %02X", cf.data[i]);
}
} }
}
if (crlf)
fprintf(outfile, "\r");
fprintf(outfile, "\n");
} }
}
fflush(outfile);
return 0; maxdev = argc - optind; /* find real number of CAN devices */
if (!maxdev) {
fprintf(stderr, "no CAN interfaces defined!\n");
print_usage(basename(argv[0]));
return 1;
}
//printf("Found %d CAN devices!\n", maxdev);
while (fgets(buf, 99, infile)) {
if (sscanf(buf, "(%ld.%ld) %s %s", &tv.tv_sec, &tv.tv_usec,
device, ascframe) != 4)
return 1;
if (!start_tv.tv_sec) { /* print banner */
start_tv = tv;
fprintf(outfile, "date %s", ctime(&start_tv.tv_sec));
fprintf(outfile, "base hex timestamps absolute%s",
(crlf)?"\r\n":"\n");
fprintf(outfile, "no internal events logged%s",
(crlf)?"\r\n":"\n");
}
for (i=0, devno=0; i<maxdev; i++) {
if (!strcmp(device, argv[optind+i])) {
devno = i+1; /* start with channel '1' */
break;
}
}
if (devno) { /* only convert for selected CAN devices */
if (parse_canframe(ascframe, &cf))
return 1;
tv.tv_sec = tv.tv_sec - start_tv.tv_sec;
tv.tv_usec = tv.tv_usec - start_tv.tv_usec;
if (tv.tv_usec < 0)
tv.tv_sec--, tv.tv_usec += 1000000;
if (tv.tv_sec < 0)
tv.tv_sec = tv.tv_usec = 0;
if (d4)
fprintf(outfile, "%4ld.%04ld ", tv.tv_sec, tv.tv_usec/100);
else
fprintf(outfile, "%4ld.%06ld ", tv.tv_sec, tv.tv_usec);
fprintf(outfile, "%-2d ", devno); /* channel number left aligned */
if (cf.can_id & CAN_ERR_FLAG)
fprintf(outfile, "ErrorFrame");
else {
sprintf(id, "%X%c", cf.can_id & CAN_EFF_MASK,
(cf.can_id & CAN_EFF_FLAG)?'x':' ');
fprintf(outfile, "%-15s Rx ", id);
if (cf.can_id & CAN_RTR_FLAG)
fprintf(outfile, "r"); /* RTR frame */
else {
fprintf(outfile, "d %d", cf.can_dlc); /* data frame */
for (i = 0; i < cf.can_dlc; i++) {
fprintf(outfile, " %02X", cf.data[i]);
}
}
}
if (crlf)
fprintf(outfile, "\r");
fprintf(outfile, "\n");
}
}
fflush(outfile);
return 0;
} }

View File

@ -54,17 +54,17 @@
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
char buf[100], timestamp[100], device[100], ascframe[100]; char buf[100], timestamp[100], device[100], ascframe[100];
struct can_frame cf; struct can_frame cf;
while (fgets(buf, 99, stdin)) { while (fgets(buf, 99, stdin)) {
if (sscanf(buf, "%s %s %s", timestamp, device, ascframe) != 3) if (sscanf(buf, "%s %s %s", timestamp, device, ascframe) != 3)
return 1; return 1;
if (parse_canframe(ascframe, &cf)) if (parse_canframe(ascframe, &cf))
return 1; return 1;
sprint_long_canframe(ascframe, &cf, 1); /* with ASCII output */ sprint_long_canframe(ascframe, &cf, 1); /* with ASCII output */
printf("%s %s %s\n", timestamp, device, ascframe); printf("%s %s %s\n", timestamp, device, ascframe);
} }
return 0; return 0;
} }

154
vcan.c
View File

@ -33,15 +33,15 @@
enum enum
{ {
IFLA_INFO_UNSPEC, IFLA_INFO_UNSPEC,
IFLA_INFO_NAME, IFLA_INFO_NAME,
IFLA_INFO_DATA, IFLA_INFO_DATA,
IFLA_INFO_XSTATS, IFLA_INFO_XSTATS,
__IFLA_INFO_MAX, __IFLA_INFO_MAX,
}; };
#endif #endif
#define NLMSG_TAIL(nmsg) \ #define NLMSG_TAIL(nmsg) \
((struct rtattr *)(((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) ((struct rtattr *)(((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
@ -49,101 +49,101 @@ int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
void usage() void usage()
{ {
fprintf(stderr, "Usage: vcan create\n" fprintf(stderr, "Usage: vcan create\n"
" vcan delete iface\n"); " vcan delete iface\n");
exit(1); exit(1);
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int s; int s;
char *cmd, *dev; char *cmd, *dev;
struct { struct {
struct nlmsghdr n; struct nlmsghdr n;
struct ifinfomsg i; struct ifinfomsg i;
char buf[1024]; char buf[1024];
} req; } req;
struct sockaddr_nl nladdr; struct sockaddr_nl nladdr;
struct rtattr *linkinfo; struct rtattr *linkinfo;
#ifdef OBSOLETE #ifdef OBSOLETE
fprintf(stderr, "This program is a temporary hack and is now obsolete.\n" fprintf(stderr, "This program is a temporary hack and is now obsolete.\n"
"Please use ip(8) instead, i.e.\n" "Please use ip(8) instead, i.e.\n"
" ip link add type vcan or\n" " ip link add type vcan or\n"
" ip link delete iface\n"); " ip link delete iface\n");
exit(1); exit(1);
#endif #endif
if (argc < 2) if (argc < 2)
usage(); usage();
cmd = argv[1]; cmd = argv[1];
s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
memset(&req, 0, sizeof(req)); memset(&req, 0, sizeof(req));
if (strcmp(cmd, "create") == 0) { if (strcmp(cmd, "create") == 0) {
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL; req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
req.n.nlmsg_type = RTM_NEWLINK; req.n.nlmsg_type = RTM_NEWLINK;
req.n.nlmsg_seq = 0; req.n.nlmsg_seq = 0;
req.i.ifi_family = AF_UNSPEC; req.i.ifi_family = AF_UNSPEC;
linkinfo = NLMSG_TAIL(&req.n); linkinfo = NLMSG_TAIL(&req.n);
addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0); addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, "vcan", strlen("vcan")); addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, "vcan", strlen("vcan"));
linkinfo->rta_len = (void*)NLMSG_TAIL(&req.n) - (void*)linkinfo; linkinfo->rta_len = (void*)NLMSG_TAIL(&req.n) - (void*)linkinfo;
} else if (strcmp(cmd, "delete") == 0) { } else if (strcmp(cmd, "delete") == 0) {
if (argc < 3) if (argc < 3)
usage(); usage();
dev = argv[2]; dev = argv[2];
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_flags = NLM_F_REQUEST;
req.n.nlmsg_type = RTM_DELLINK; req.n.nlmsg_type = RTM_DELLINK;
req.i.ifi_family = AF_UNSPEC; req.i.ifi_family = AF_UNSPEC;
req.i.ifi_index = if_nametoindex(dev); req.i.ifi_index = if_nametoindex(dev);
} else } else
usage(); usage();
memset(&nladdr, 0, sizeof(nladdr)); memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK; nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = 0; nladdr.nl_pid = 0;
nladdr.nl_groups = 0; nladdr.nl_groups = 0;
#if 1 #if 1
sendto(s, &req, req.n.nlmsg_len, 0, sendto(s, &req, req.n.nlmsg_len, 0,
(struct sockaddr*)&nladdr, sizeof(nladdr)); (struct sockaddr*)&nladdr, sizeof(nladdr));
#else #else
{ {
int i; int i;
for (i = 0; i < req.n.nlmsg_len; i++) { for (i = 0; i < req.n.nlmsg_len; i++) {
printf(" %02x", ((unsigned char*)&req)[i]); printf(" %02x", ((unsigned char*)&req)[i]);
if (i % 16 == 15) if (i % 16 == 15)
putchar('\n');
}
putchar('\n'); putchar('\n');
} }
putchar('\n');
}
#endif #endif
close(s); close(s);
return 0; return 0;
} }
int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
int alen) int alen)
{ {
int len = RTA_LENGTH(alen); int len = RTA_LENGTH(alen);
struct rtattr *rta; struct rtattr *rta;
if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) { if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n", fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n",
maxlen); maxlen);
return -1; return -1;
} }
rta = NLMSG_TAIL(n); rta = NLMSG_TAIL(n);
rta->rta_type = type; rta->rta_type = type;
rta->rta_len = len; rta->rta_len = len;
memcpy(RTA_DATA(rta), data, alen); memcpy(RTA_DATA(rta), data, alen);
n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
return 0; return 0;
} }