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)
{
fprintf(stderr, "Usage: %s\n", prg);
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
fprintf(stderr, " -O <outfile> (default stdout)\n");
fprintf(stderr, "Usage: %s\n", prg);
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
fprintf(stderr, " -O <outfile> (default stdout)\n");
}
void prframe(FILE *file, struct timeval *tv, int dev, struct can_frame *cf) {
fprintf(file, "(%ld.%06ld) ", tv->tv_sec, tv->tv_usec);
if (dev > 0)
fprintf(file, "can%d ", dev-1);
else
fprintf(file, "canX ");
fprint_canframe(file, cf, "\n", 0);
fprintf(file, "(%ld.%06ld) ", tv->tv_sec, tv->tv_usec);
if (dev > 0)
fprintf(file, "can%d ", dev-1);
else
fprintf(file, "canX ");
fprint_canframe(file, cf, "\n", 0);
}
void get_can_id(struct can_frame *cf, char *idstring, int base) {
if (idstring[strlen(idstring)-1] == 'x') {
cf->can_id = CAN_EFF_FLAG;
idstring[strlen(idstring)-1] = 0;
} else
cf->can_id = 0;
if (idstring[strlen(idstring)-1] == 'x') {
cf->can_id = CAN_EFF_FLAG;
idstring[strlen(idstring)-1] = 0;
} else
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,
struct timeval *date_tv, char timestamps, int dplace) {
if (dplace == 4) /* shift values having only 4 decimal places */
read_tv->tv_usec *= 100; /* and need for 6 */
if (dplace == 4) /* shift values having only 4 decimal places */
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_usec = date_tv->tv_usec + read_tv->tv_usec;
tv->tv_sec = date_tv->tv_sec + read_tv->tv_sec;
tv->tv_usec = date_tv->tv_usec + read_tv->tv_usec;
} else { /* relative */
} else { /* relative */
if (((!tv->tv_sec) && (!tv->tv_usec)) &&
(date_tv->tv_sec || date_tv->tv_usec)) {
tv->tv_sec = date_tv->tv_sec; /* initial date/time */
tv->tv_usec = date_tv->tv_usec;
if (((!tv->tv_sec) && (!tv->tv_usec)) &&
(date_tv->tv_sec || date_tv->tv_usec)) {
tv->tv_sec = date_tv->tv_sec; /* initial date/time */
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;
tv->tv_usec += read_tv->tv_usec;
}
if (tv->tv_usec > 1000000) {
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) {
char ctmp[10];
int itmp;
char ctmp[10];
int itmp;
struct tm tms;
struct tm tms;
if (sscanf(date, "%9s %d %9s %9s %d", ctmp, &itmp, ctmp, ctmp, &itmp) == 5) {
/* assume EN/US date due to existing am/pm field */
if (sscanf(date, "%9s %d %9s %9s %d", ctmp, &itmp, ctmp, ctmp, &itmp) == 5) {
/* assume EN/US date due to existing am/pm field */
if (!setlocale(LC_TIME, "en_US"))
return 1;
if (!setlocale(LC_TIME, "en_US"))
return 1;
if (!strptime(date, "%B %d %r %Y", &tms))
return 1;
if (!strptime(date, "%B %d %r %Y", &tms))
return 1;
} else {
/* assume DE date due to non existing am/pm field */
} else {
/* assume DE date due to non existing am/pm field */
if (sscanf(date, "%9s %d %9s %d", ctmp, &itmp, ctmp, &itmp) != 4)
return 1;
if (sscanf(date, "%9s %d %9s %d", ctmp, &itmp, ctmp, &itmp) != 4)
return 1;
if (!setlocale(LC_TIME, "de_DE"))
return 1;
if (!setlocale(LC_TIME, "de_DE"))
return 1;
if (!strptime(date, "%B %d %T %Y", &tms))
return 1;
}
if (!strptime(date, "%B %d %T %Y", &tms))
return 1;
}
//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_mday, tms.tm_mon+1, tms.tm_year+1900);
//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_mday, tms.tm_mon+1, tms.tm_year+1900);
tv->tv_sec = mktime(&tms);
tv->tv_sec = mktime(&tms);
if (tv->tv_sec < 0)
return 1;
if (tv->tv_sec < 0)
return 1;
return 0;
return 0;
}
int main(int argc, char **argv)
{
char buf[100], tmp1[100], tmp2[100];
char buf[100], tmp1[100], tmp2[100];
FILE *infile = stdin;
FILE *outfile = stdout;
static int verbose;
struct can_frame cf;
static struct timeval tv; /* current frame timestamp */
static struct timeval read_tv; /* frame timestamp from ASC file */
static struct timeval date_tv; /* date of the ASC file */
static int dplace; /* decimal place 4 or 6 or uninitialized */
static char base; /* 'd'ec or 'h'ex */
static char timestamps; /* 'a'bsolute or 'r'elative */
FILE *infile = stdin;
FILE *outfile = stdout;
static int verbose;
struct can_frame cf;
static struct timeval tv; /* current frame timestamp */
static struct timeval read_tv; /* frame timestamp from ASC file */
static struct timeval date_tv; /* date of the ASC file */
static int dplace; /* decimal place 4 or 6 or uninitialized */
static char base; /* 'd'ec or 'h'ex */
static char timestamps; /* 'a'bsolute or 'r'elative */
int interface;
char rtr;
int dlc = 0;
int data[8];
int i, found, opt;
int interface;
char rtr;
int dlc = 0;
int data[8];
int i, found, opt;
while ((opt = getopt(argc, argv, "I:O:v")) != -1) {
switch (opt) {
case 'I':
infile = fopen(optarg, "r");
if (!infile) {
perror("infile");
return 1;
}
break;
while ((opt = getopt(argc, argv, "I:O:v")) != -1) {
switch (opt) {
case 'I':
infile = fopen(optarg, "r");
if (!infile) {
perror("infile");
return 1;
}
break;
case 'O':
outfile = fopen(optarg, "w");
if (!outfile) {
perror("outfile");
return 1;
}
break;
case 'O':
outfile = fopen(optarg, "w");
if (!outfile) {
perror("outfile");
return 1;
}
break;
case 'v':
verbose = 1;
break;
case 'v':
verbose = 1;
break;
default:
fprintf(stderr, "Unknown option %c\n", opt);
print_usage(basename(argv[0]));
return 1;
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;
default:
fprintf(stderr, "Unknown option %c\n", opt);
print_usage(basename(argv[0]));
return 1;
break;
}
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 */
if ((!date_tv.tv_sec) &&
(!strncmp(buf, "date", 4))) {
/* the representation of a valid CAN frame is known here */
/* so try to get CAN frames and ErrorFrames and convert them */
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);
/* 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 (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;
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);
}
}
} else
continue; /* dplace remains zero until first found CAN frame */
}
/* the representation of a valid CAN frame is known here */
/* 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;
fclose(outfile);
return 0;
}

View File

@ -74,11 +74,11 @@
extern int optind, opterr, optopt;
static struct {
char devname[IFNAMSIZ+1];
unsigned int bitrate;
unsigned int recv_frames;
unsigned int recv_bits_total;
unsigned int recv_bits_payload;
char devname[IFNAMSIZ+1];
unsigned int bitrate;
unsigned int recv_frames;
unsigned int recv_bits_total;
unsigned int recv_bits_payload;
} stat[MAXSOCK+1];
static int max_devname_len; /* to prevent frazzled device name output */
@ -92,289 +92,289 @@ static char *prg;
void print_usage(char *prg)
{
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\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, " -c (colorize lines)\n");
fprintf(stderr, " -b (show bargraph in %d%% resolution)\n", PERCENTRES);
fprintf(stderr, " -r (redraw the terminal - similar to top)\n");
fprintf(stderr, "\n");
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, "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, "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, "\nExample:\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, " can0@100000 805 74491 36656 74%% |XXXXXXXXXXXXXX......|\n");
fprintf(stderr, " can1@500000 796 75140 37728 15%% |XXX.................|\n");
fprintf(stderr, " can2@500000 0 0 0 0%% |....................|\n");
fprintf(stderr, " can3@500000 47 4633 2424 0%% |....................|\n");
fprintf(stderr, "\n");
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\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, " -c (colorize lines)\n");
fprintf(stderr, " -b (show bargraph in %d%% resolution)\n", PERCENTRES);
fprintf(stderr, " -r (redraw the terminal - similar to top)\n");
fprintf(stderr, "\n");
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, "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, "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, "\nExample:\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, " can0@100000 805 74491 36656 74%% |XXXXXXXXXXXXXX......|\n");
fprintf(stderr, " can1@500000 796 75140 37728 15%% |XXX.................|\n");
fprintf(stderr, " can2@500000 0 0 0 0%% |....................|\n");
fprintf(stderr, " can3@500000 47 4633 2424 0%% |....................|\n");
fprintf(stderr, "\n");
}
void sigterm(int signo)
{
exit(0);
exit(0);
}
void printstats(int signo)
{
int i, j, percent;
int i, j, percent;
if (redraw)
printf("%s", CSR_HOME);
if (redraw)
printf("%s", CSR_HOME);
if (timestamp) {
time_t currtime;
struct tm now;
if (timestamp) {
time_t currtime;
struct tm now;
if (time(&currtime) == (time_t)-1) {
perror("time");
exit(1);
if (time(&currtime) == (time_t)-1) {
perror("time");
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",
prg,
now.tm_year + 1900,
now.tm_mon + 1,
now.tm_mday,
now.tm_hour,
now.tm_min,
now.tm_sec);
}
if (color)
if (i%2)
printf("%s", FGRED);
else
printf("%s", FGBLUE);
for (i=0; i<currmax; i++) {
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");
if (stat[i].bitrate)
percent = (stat[i].recv_bits_total*100)/stat[i].bitrate;
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");
stat[i].recv_frames = 0;
stat[i].recv_bits_total = 0;
stat[i].recv_bits_payload = 0;
}
printf("\n");
alarm(1);
alarm(1);
}
int main(int argc, char **argv)
{
fd_set rdfs;
int s[MAXSOCK];
fd_set rdfs;
int s[MAXSOCK];
int opt;
char *ptr, *nptr;
struct sockaddr_can addr;
struct can_frame frame;
int nbytes, i;
struct ifreq ifr;
sigset_t sigmask, savesigmask;
int opt;
char *ptr, *nptr;
struct sockaddr_can addr;
struct can_frame frame;
int nbytes, i;
struct ifreq ifr;
sigset_t sigmask, savesigmask;
signal(SIGTERM, sigterm);
signal(SIGHUP, sigterm);
signal(SIGINT, sigterm);
signal(SIGTERM, sigterm);
signal(SIGHUP, 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) {
switch (opt) {
case 'r':
redraw = 1;
break;
while ((opt = getopt(argc, argv, "rtbch?")) != -1) {
switch (opt) {
case 'r':
redraw = 1;
break;
case 't':
timestamp = 1;
break;
case 't':
timestamp = 1;
break;
case 'b':
bargraph = 1;
break;
case 'b':
bargraph = 1;
break;
case 'c':
color = 1;
break;
case 'c':
color = 1;
break;
default:
print_usage(prg);
exit(1);
break;
default:
print_usage(prg);
exit(1);
break;
}
}
}
if (optind == argc) {
print_usage(prg);
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;
if (optind == argc) {
print_usage(prg);
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;
}
#ifdef DEBUG
printf("open %d '%s'.\n", i, ptr);
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;
}
s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (s[i] < 0) {
perror("socket");
return 1;
}
nptr = strchr(ptr, '@');
nptr = strchr(ptr, '@');
if (!nptr) {
print_usage(prg);
return 1;
}
if (!nptr) {
print_usage(prg);
return 1;
}
nbytes = nptr - ptr; /* interface name is up the first '@' */
nbytes = nptr - ptr; /* interface name is up the first '@' */
if (nbytes >= IFNAMSIZ) {
printf("name of CAN device '%s' is too long!\n", ptr);
return 1;
}
if (nbytes >= IFNAMSIZ) {
printf("name of CAN device '%s' is too long!\n", ptr);
return 1;
}
strncpy(stat[i].devname, ptr, nbytes);
memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
strncpy(ifr.ifr_name, ptr, nbytes);
strncpy(stat[i].devname, ptr, nbytes);
memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
strncpy(ifr.ifr_name, ptr, nbytes);
if (nbytes > max_devname_len)
max_devname_len = nbytes; /* for nice printing */
if (nbytes > max_devname_len)
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) {
printf("invalid bitrate for CAN device '%s'!\n", ptr);
return 1;
}
if (!stat[i].bitrate || stat[i].bitrate > 1000000) {
printf("invalid bitrate for CAN device '%s'!\n", ptr);
return 1;
}
nbytes = strlen(nptr+1);
if (nbytes > max_bitrate_len)
max_bitrate_len = nbytes; /* for nice printing */
nbytes = strlen(nptr+1);
if (nbytes > max_bitrate_len)
max_bitrate_len = nbytes; /* for nice printing */
#ifdef DEBUG
printf("using interface name '%s'.\n", ifr.ifr_name);
printf("using interface name '%s'.\n", ifr.ifr_name);
#endif
if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX");
exit(1);
if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX");
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;
addr.can_ifindex = ifr.ifr_ifindex;
alarm(1);
if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind");
return 1;
if (redraw)
printf("%s", CLR_SCREEN);
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++)
FD_SET(s[i], &rdfs);
close(s[i]);
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;
}
}
}
for (i=0; i<currmax; i++)
close(s[i]);
return 0;
return 0;
}

830
candump.c
View File

@ -98,476 +98,476 @@ static volatile int running = 1;
void print_usage(char *prg)
{
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\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, " -c (increment color mode level)\n");
fprintf(stderr, " -i (binary output - may exceed 80 chars/line)\n");
fprintf(stderr, " -a (enable additional ASCII output)\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 - like '-b' with disabled loopback)\n");
fprintf(stderr, " -l (log CAN-frames into file)\n");
fprintf(stderr, " -L (use log file format on stdout)\n");
fprintf(stderr, "\n");
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, "\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, " #<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, "CAN IDs, masks and data content are given and expected in hexadecimal values.\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 -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, "\n");
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\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, " -c (increment color mode level)\n");
fprintf(stderr, " -i (binary output - may exceed 80 chars/line)\n");
fprintf(stderr, " -a (enable additional ASCII output)\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 - like '-b' with disabled loopback)\n");
fprintf(stderr, " -l (log CAN-frames into file)\n");
fprintf(stderr, " -L (use log file format on stdout)\n");
fprintf(stderr, "\n");
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, "\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, " #<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, "CAN IDs, masks and data content are given and expected in hexadecimal values.\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 -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, "\n");
}
void sigterm(int signo)
{
running = 0;
running = 0;
}
int idx2dindex(int ifidx, int socket) {
int i;
struct ifreq ifr;
int i;
struct ifreq ifr;
for (i=0; i < MAXIFNAMES; i++) {
if (dindex[i] == ifidx)
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++) {
if (dindex[i] == ifidx)
return i;
}
}
for (i=0; i < MAXIFNAMES; i++)
if (!dindex[i]) /* free entry */
break;
/* create new interface index cache entry */
if (i == MAXIFNAMES) {
printf("Interface index cache only supports %d interfaces.\n",
MAXIFNAMES);
exit(1);
}
/* 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;
}
}
dindex[i] = ifidx;
for (i=0; i < MAXIFNAMES; i++)
if (!dindex[i]) /* free entry */
break;
ifr.ifr_ifindex = ifidx;
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
perror("SIOCGIFNAME");
if (i == MAXIFNAMES) {
printf("Interface index cache only supports %d interfaces.\n",
MAXIFNAMES);
exit(1);
}
if (max_devname_len < strlen(ifr.ifr_name))
max_devname_len = strlen(ifr.ifr_name);
dindex[i] = ifidx;
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
printf("new index %d (%s)\n", i, devname[i]);
printf("new index %d (%s)\n", i, devname[i]);
#endif
return i;
return i;
}
int main(int argc, char **argv)
{
fd_set rdfs;
int s[MAXSOCK];
int bridge = 0;
unsigned char timestamp = 0;
unsigned char silent = 0;
unsigned char silentani = 0;
unsigned char color = 0;
unsigned char view = 0;
unsigned char log = 0;
unsigned char logfrmt = 0;
int opt, ret;
int currmax, numfilter;
char *ptr, *nptr;
struct sockaddr_can addr;
struct can_filter rfilter[MAXFILTER];
can_err_mask_t err_mask;
struct can_frame frame;
int nbytes, i;
struct ifreq ifr;
struct timeval tv, last_tv;
FILE *logfile = NULL;
fd_set rdfs;
int s[MAXSOCK];
int bridge = 0;
unsigned char timestamp = 0;
unsigned char silent = 0;
unsigned char silentani = 0;
unsigned char color = 0;
unsigned char view = 0;
unsigned char log = 0;
unsigned char logfrmt = 0;
int opt, ret;
int currmax, numfilter;
char *ptr, *nptr;
struct sockaddr_can addr;
struct can_filter rfilter[MAXFILTER];
can_err_mask_t err_mask;
struct can_frame frame;
int nbytes, i;
struct ifreq ifr;
struct timeval tv, last_tv;
FILE *logfile = NULL;
signal(SIGTERM, sigterm);
signal(SIGHUP, sigterm);
signal(SIGINT, sigterm);
signal(SIGTERM, sigterm);
signal(SIGHUP, sigterm);
signal(SIGINT, sigterm);
last_tv.tv_sec = 0;
last_tv.tv_usec = 0;
last_tv.tv_sec = 0;
last_tv.tv_usec = 0;
while ((opt = getopt(argc, argv, "t:cias:b:B:lLh?")) != -1) {
switch (opt) {
case 't':
timestamp = optarg[0];
if ((timestamp != 'a') && (timestamp != 'A') &&
(timestamp != 'd') && (timestamp != 'z')) {
printf("%s: unknown timestamp mode '%c' - ignored\n",
basename(argv[0]), optarg[0]);
timestamp = 0;
}
break;
while ((opt = getopt(argc, argv, "t:cias:b:B:lLh?")) != -1) {
switch (opt) {
case 't':
timestamp = optarg[0];
if ((timestamp != 'a') && (timestamp != 'A') &&
(timestamp != 'd') && (timestamp != 'z')) {
printf("%s: unknown timestamp mode '%c' - ignored\n",
basename(argv[0]), optarg[0]);
timestamp = 0;
}
break;
case 'c':
color++;
break;
case 'c':
color++;
break;
case 'i':
view |= CANLIB_VIEW_BINARY;
break;
case 'i':
view |= CANLIB_VIEW_BINARY;
break;
case 'a':
view |= CANLIB_VIEW_ASCII;
break;
case 'a':
view |= CANLIB_VIEW_ASCII;
break;
case 's':
silent = atoi(optarg);
break;
case 's':
silent = atoi(optarg);
break;
case 'b':
case 'B':
if (strlen(optarg) >= IFNAMSIZ) {
printf("Name of CAN device '%s' is too long!\n\n", optarg);
case 'b':
case 'B':
if (strlen(optarg) >= IFNAMSIZ) {
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;
} else {
bridge = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (bridge < 0) {
perror("bridge socket");
return 1;
}
for (i=0; i < currmax; i++) {
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;
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;
}
for (i=0; i < currmax; i++) {
ptr = argv[optind+i];
nptr = strchr(ptr, ',');
memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
strncpy(ifr.ifr_name, ptr, nbytes);
#ifdef DEBUG
printf("open %d '%s'.\n", i, ptr);
printf("using interface name '%s'.\n", ifr.ifr_name);
#endif
s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (s[i] < 0) {
perror("socket");
return 1;
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) {
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)
nbytes = nptr - ptr; /* interface name is up the first ',' */
else
nbytes = strlen(ptr); /* no ',' found => no filter definitions */
if (log) {
time_t currtime;
struct tm now;
char fname[sizeof("candump-2006-11-20_202026.log")+1];
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;
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 (time(&currtime) == (time_t)-1) {
perror("time");
return 1;
}
if (numfilter > MAXFILTER) {
printf("Too many filters specified for '%s'.\n",
ifr.ifr_name);
exit(1);
localtime_r(&currtime, &now);
sprintf(fname, "candump-%04d-%02d-%02d_%02d%02d%02d.log",
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",
now.tm_year + 1900,
now.tm_mon + 1,
now.tm_mday,
now.tm_hour,
now.tm_min,
now.tm_sec);
FD_ZERO(&rdfs);
for (i=0; i<currmax; i++)
FD_SET(s[i], &rdfs);
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");
if (!logfile) {
perror("logfile");
return 1;
for (i=0; i<currmax; i++) { /* check all CAN RAW sockets */
if (FD_ISSET(s[i], &rdfs)) {
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++)
FD_SET(s[i], &rdfs);
close(s[i]);
if ((ret = select(s[currmax-1]+1, &rdfs, NULL, NULL, NULL)) < 0) {
//perror("select");
running = 0;
continue;
}
if (bridge)
close(bridge);
for (i=0; i<currmax; i++) { /* check all CAN RAW sockets */
if (log)
fclose(logfile);
if (FD_ISSET(s[i], &rdfs)) {
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;
return 0;
}

500
cangen.c
View File

@ -80,306 +80,306 @@ static unsigned long long enobufs_count;
void print_usage(char *prg)
{
fprintf(stderr, "\n%s: generate CAN frames\n\n", prg);
fprintf(stderr, "Usage: %s [options] <CAN interface>\n", prg);
fprintf(stderr, "Options: -g <ms> (gap in milli seconds "
"- default: %d ms)\n", DEFAULT_GAP);
fprintf(stderr, " -e (generate extended frame mode "
"(EFF) CAN frames)\n");
fprintf(stderr, " -I <mode> (CAN ID"
" generation mode - see below)\n");
fprintf(stderr, " -L <mode> (CAN data length code (dlc)"
" generation mode - see below)\n");
fprintf(stderr, " -D <mode> (CAN data (payload)"
" generation mode - see below)\n");
fprintf(stderr, " -i (ignore -ENOBUFS return values on"
" write() syscalls)\n");
fprintf(stderr, " -x (disable local loopback of "
"generated CAN frames)\n");
fprintf(stderr, " -v (increment verbose level for "
"printing sent CAN frames)\n\n");
fprintf(stderr, "Generation modes:\n");
fprintf(stderr, "'r' => random values (default)\n");
fprintf(stderr, "'i' => increment values\n");
fprintf(stderr, "<hexvalue> => fix value using <hexvalue>\n\n");
fprintf(stderr, "When incrementing the CAN data the data length code "
"minimum is set to 1.\n");
fprintf(stderr, "CAN IDs and data content are given and expected in hexadecimal values.\n\n");
fprintf(stderr, "Examples:\n");
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, "%s vcan0 -e -L i -v -v -v ", prg);
fprintf(stderr, "(generate EFF frames, incr. length)\n");
fprintf(stderr, "%s vcan0 -D 11223344DEADBEEF -L 8 ", prg);
fprintf(stderr, "(fixed CAN data payload and length)\n");
fprintf(stderr, "%s vcan0 -g 0 -i -x ", prg);
fprintf(stderr, "(full load test ignoring -ENOBUFS)\n");
fprintf(stderr, "%s vcan0 ", prg);
fprintf(stderr, "(my favourite default :)\n\n");
fprintf(stderr, "\n%s: generate CAN frames\n\n", prg);
fprintf(stderr, "Usage: %s [options] <CAN interface>\n", prg);
fprintf(stderr, "Options: -g <ms> (gap in milli seconds "
"- default: %d ms)\n", DEFAULT_GAP);
fprintf(stderr, " -e (generate extended frame mode "
"(EFF) CAN frames)\n");
fprintf(stderr, " -I <mode> (CAN ID"
" generation mode - see below)\n");
fprintf(stderr, " -L <mode> (CAN data length code (dlc)"
" generation mode - see below)\n");
fprintf(stderr, " -D <mode> (CAN data (payload)"
" generation mode - see below)\n");
fprintf(stderr, " -i (ignore -ENOBUFS return values on"
" write() syscalls)\n");
fprintf(stderr, " -x (disable local loopback of "
"generated CAN frames)\n");
fprintf(stderr, " -v (increment verbose level for "
"printing sent CAN frames)\n\n");
fprintf(stderr, "Generation modes:\n");
fprintf(stderr, "'r' => random values (default)\n");
fprintf(stderr, "'i' => increment values\n");
fprintf(stderr, "<hexvalue> => fix value using <hexvalue>\n\n");
fprintf(stderr, "When incrementing the CAN data the data length code "
"minimum is set to 1.\n");
fprintf(stderr, "CAN IDs and data content are given and expected in hexadecimal values.\n\n");
fprintf(stderr, "Examples:\n");
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, "%s vcan0 -e -L i -v -v -v ", prg);
fprintf(stderr, "(generate EFF frames, incr. length)\n");
fprintf(stderr, "%s vcan0 -D 11223344DEADBEEF -L 8 ", prg);
fprintf(stderr, "(fixed CAN data payload and length)\n");
fprintf(stderr, "%s vcan0 -g 0 -i -x ", prg);
fprintf(stderr, "(full load test ignoring -ENOBUFS)\n");
fprintf(stderr, "%s vcan0 ", prg);
fprintf(stderr, "(my favourite default :)\n\n");
}
void sigterm(int signo)
{
running = 0;
running = 0;
}
int main(int argc, char **argv)
{
unsigned long gap = DEFAULT_GAP;
unsigned char ignore_enobufs = 0;
unsigned char extended = 0;
unsigned char id_mode = MODE_RANDOM;
unsigned char data_mode = MODE_RANDOM;
unsigned char dlc_mode = MODE_RANDOM;
unsigned char loopback_disable = 0;
unsigned char verbose = 0;
uint64_t incdata = 0;
unsigned long gap = DEFAULT_GAP;
unsigned char ignore_enobufs = 0;
unsigned char extended = 0;
unsigned char id_mode = MODE_RANDOM;
unsigned char data_mode = MODE_RANDOM;
unsigned char dlc_mode = MODE_RANDOM;
unsigned char loopback_disable = 0;
unsigned char verbose = 0;
uint64_t incdata = 0;
int opt;
int s; /* socket */
int opt;
int s; /* socket */
struct sockaddr_can addr;
static struct can_frame frame;
int nbytes;
int i;
struct ifreq ifr;
struct sockaddr_can addr;
static struct can_frame frame;
int nbytes;
int i;
struct ifreq ifr;
struct timespec ts;
struct timespec ts;
signal(SIGTERM, sigterm);
signal(SIGHUP, sigterm);
signal(SIGINT, sigterm);
signal(SIGTERM, sigterm);
signal(SIGHUP, sigterm);
signal(SIGINT, sigterm);
while ((opt = getopt(argc, argv, "ig:eI:L:D:xvh?")) != -1) {
switch (opt) {
while ((opt = getopt(argc, argv, "ig:eI:L:D:xvh?")) != -1) {
switch (opt) {
case 'i':
ignore_enobufs = 1;
break;
case 'i':
ignore_enobufs = 1;
break;
case 'g':
gap = strtoul(optarg, NULL, 10);
break;
case 'g':
gap = strtoul(optarg, NULL, 10);
break;
case 'e':
extended = 1;
break;
case 'e':
extended = 1;
break;
case 'I':
if (optarg[0] == 'r') {
id_mode = MODE_RANDOM;
} else if (optarg[0] == 'i') {
id_mode = MODE_INCREMENT;
} else {
id_mode = MODE_FIX;
frame.can_id = strtoul(optarg, NULL, 16);
}
break;
case 'I':
if (optarg[0] == 'r') {
id_mode = MODE_RANDOM;
} else if (optarg[0] == 'i') {
id_mode = MODE_INCREMENT;
} else {
id_mode = MODE_FIX;
frame.can_id = strtoul(optarg, NULL, 16);
}
break;
case 'L':
if (optarg[0] == 'r') {
dlc_mode = MODE_RANDOM;
} else if (optarg[0] == 'i') {
dlc_mode = MODE_INCREMENT;
} else {
dlc_mode = MODE_FIX;
frame.can_dlc = atoi(optarg)%9;
}
break;
case 'L':
if (optarg[0] == 'r') {
dlc_mode = MODE_RANDOM;
} else if (optarg[0] == 'i') {
dlc_mode = MODE_INCREMENT;
} else {
dlc_mode = MODE_FIX;
frame.can_dlc = atoi(optarg)%9;
}
break;
case 'D':
if (optarg[0] == 'r') {
data_mode = MODE_RANDOM;
} else if (optarg[0] == 'i') {
data_mode = MODE_INCREMENT;
} else {
data_mode = MODE_FIX;
incdata = strtoull(optarg, NULL, 16);
for (i=0; i<8 ;i++)
frame.data[i] = (incdata >> (7-i)*8) & 0xFFULL;
}
break;
case 'D':
if (optarg[0] == 'r') {
data_mode = MODE_RANDOM;
} else if (optarg[0] == 'i') {
data_mode = MODE_INCREMENT;
} else {
data_mode = MODE_FIX;
incdata = strtoull(optarg, NULL, 16);
for (i=0; i<8 ;i++)
frame.data[i] = (incdata >> (7-i)*8) & 0xFFULL;
}
break;
case 'v':
verbose++;
break;
case 'v':
verbose++;
break;
case 'x':
loopback_disable = 1;
break;
case 'x':
loopback_disable = 1;
break;
case '?':
case 'h':
default:
print_usage(basename(argv[0]));
return 1;
break;
case '?':
case 'h':
default:
print_usage(basename(argv[0]));
return 1;
break;
}
}
}
if (optind == argc) {
print_usage(basename(argv[0]));
return 1;
}
if (optind == argc) {
print_usage(basename(argv[0]));
return 1;
}
ts.tv_sec = gap / 1000;
ts.tv_nsec = (gap % 1000) * 1000000;
ts.tv_sec = gap / 1000;
ts.tv_nsec = (gap % 1000) * 1000000;
if (id_mode == MODE_FIX) {
if (id_mode == MODE_FIX) {
/* recognize obviously missing commandline option */
if ((frame.can_id > 0x7FF) && !extended) {
printf("The given CAN-ID is greater than 0x7FF and "
"the '-e' option is not set.\n");
return 1;
/* recognize obviously missing commandline option */
if ((frame.can_id > 0x7FF) && !extended) {
printf("The given CAN-ID is greater than 0x7FF and "
"the '-e' option is not set.\n");
return 1;
}
if (extended)
frame.can_id &= CAN_EFF_MASK;
else
frame.can_id &= CAN_SFF_MASK;
}
if (extended)
frame.can_id &= CAN_EFF_MASK;
else
frame.can_id &= CAN_SFF_MASK;
}
frame.can_id |= CAN_EFF_FLAG;
if (extended)
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)
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");
if (strlen(argv[optind]) >= IFNAMSIZ) {
printf("Name of CAN device '%s' is too long!\n\n", argv[optind]);
return 1;
}
if (!ignore_enobufs) {
perror("write");
}
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
perror("socket");
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))
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;
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) {
frame.can_id &= CAN_EFF_MASK;
frame.can_id |= CAN_EFF_FLAG;
} else
frame.can_id &= CAN_SFF_MASK;
setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
&loopback, sizeof(loopback));
}
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 (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind");
return 1;
}
if (data_mode == MODE_INCREMENT) {
while (running) {
incdata++;
if (id_mode == MODE_RANDOM) {
for (i=0; i<8 ;i++)
frame.data[i] = (incdata >> i*8) & 0xFFULL;
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 */
}
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)
printf("\nCounted %llu ENOBUFS return values on write().\n\n",
enobufs_count);
if (enobufs_count)
printf("\nCounted %llu ENOBUFS return values on write().\n\n",
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)
{
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\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, " -v <value> (ID filter value. Default 0x00000000) *\n");
fprintf(stderr, " -i <0|1> (invert the specified ID filter) *\n");
fprintf(stderr, " -e <emask> (mask for error frames)\n");
fprintf(stderr, " -p <port> (listen on port <port>. Default: %d)\n", DEFPORT);
fprintf(stderr, "\n");
fprintf(stderr, "* The CAN ID filter matches, when ...\n");
fprintf(stderr, " <received_can_id> & mask == value & mask\n");
fprintf(stderr, "\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, "\nUse interface name '%s' to receive from all CAN interfaces.\n\n", ANYDEV);
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\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, " -v <value> (ID filter value. Default 0x00000000) *\n");
fprintf(stderr, " -i <0|1> (invert the specified ID filter) *\n");
fprintf(stderr, " -e <emask> (mask for error frames)\n");
fprintf(stderr, " -p <port> (listen on port <port>. Default: %d)\n", DEFPORT);
fprintf(stderr, "\n");
fprintf(stderr, "* The CAN ID filter matches, when ...\n");
fprintf(stderr, " <received_can_id> & mask == value & mask\n");
fprintf(stderr, "\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, "\nUse interface name '%s' to receive from all CAN interfaces.\n\n", ANYDEV);
}
int idx2dindex(int ifidx, int socket)
{
int i;
struct ifreq ifr;
int i;
struct ifreq ifr;
for (i=0; i<MAXDEV; i++) {
if (dindex[i] == ifidx)
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++) {
if (dindex[i] == ifidx)
return i;
}
}
for (i=0; i < MAXDEV; i++)
if (!dindex[i]) /* free entry */
break;
/* create new interface index cache entry */
if (i == MAXDEV) {
printf("Interface index cache only supports %d interfaces.\n", MAXDEV);
exit(1);
}
/* 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;
}
}
dindex[i] = ifidx;
for (i=0; i < MAXDEV; i++)
if (!dindex[i]) /* free entry */
break;
ifr.ifr_ifindex = ifidx;
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
perror("SIOCGIFNAME");
if (i == MAXDEV) {
printf("Interface index cache only supports %d interfaces.\n", MAXDEV);
exit(1);
}
if (max_devname_len < strlen(ifr.ifr_name))
max_devname_len = strlen(ifr.ifr_name);
dindex[i] = ifidx;
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
printf("new index %d (%s)\n", i, devname[i]);
printf("new index %d (%s)\n", i, devname[i]);
#endif
return i;
return i;
}
/*
@ -156,7 +156,7 @@ int idx2dindex(int ifidx, int socket)
*/
void childdied(int i)
{
wait(NULL);
wait(NULL);
}
/*
@ -164,273 +164,273 @@ void childdied(int i)
*/
void shutdown_gra(int i)
{
exit(0);
exit(0);
}
int main(int argc, char **argv)
{
struct sigaction signalaction;
sigset_t sigset;
fd_set rdfs;
int s[MAXDEV];
int socki, accsocket;
canid_t mask[MAXDEV] = {0};
canid_t value[MAXDEV] = {0};
int inv_filter[MAXDEV] = {0};
can_err_mask_t err_mask[MAXDEV] = {0};
int opt, ret;
int currmax = 1; /* we assume at least one can bus ;-) */
struct sockaddr_can addr;
struct can_filter rfilter;
struct can_frame frame;
int nbytes, i, j;
struct ifreq ifr;
struct timeval tv, last_tv;
int port = DEFPORT;
struct sockaddr_in inaddr;
struct sockaddr_in clientaddr;
socklen_t sin_size = sizeof(clientaddr);
char temp[128];
struct sigaction signalaction;
sigset_t sigset;
fd_set rdfs;
int s[MAXDEV];
int socki, accsocket;
canid_t mask[MAXDEV] = {0};
canid_t value[MAXDEV] = {0};
int inv_filter[MAXDEV] = {0};
can_err_mask_t err_mask[MAXDEV] = {0};
int opt, ret;
int currmax = 1; /* we assume at least one can bus ;-) */
struct sockaddr_can addr;
struct can_filter rfilter;
struct can_frame frame;
int nbytes, i, j;
struct ifreq ifr;
struct timeval tv, last_tv;
int port = DEFPORT;
struct sockaddr_in inaddr;
struct sockaddr_in clientaddr;
socklen_t sin_size = sizeof(clientaddr);
char temp[128];
sigemptyset(&sigset);
signalaction.sa_handler = &childdied;
signalaction.sa_mask = sigset;
signalaction.sa_flags = 0;
sigaction(SIGCHLD, &signalaction, NULL); /* install signal for dying child */
signalaction.sa_handler = &shutdown_gra;
signalaction.sa_mask = sigset;
signalaction.sa_flags = 0;
sigaction(SIGTERM, &signalaction, NULL); /* install Signal for termination */
sigaction(SIGINT, &signalaction, NULL); /* install Signal for termination */
sigemptyset(&sigset);
signalaction.sa_handler = &childdied;
signalaction.sa_mask = sigset;
signalaction.sa_flags = 0;
sigaction(SIGCHLD, &signalaction, NULL); /* install signal for dying child */
signalaction.sa_handler = &shutdown_gra;
signalaction.sa_mask = sigset;
signalaction.sa_flags = 0;
sigaction(SIGTERM, &signalaction, NULL); /* install Signal for termination */
sigaction(SIGINT, &signalaction, NULL); /* install Signal for termination */
last_tv.tv_sec = 0;
last_tv.tv_usec = 0;
last_tv.tv_sec = 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) {
case 'm':
i = sscanf(optarg, "%x,%x,%x,%x,%x,%x",
&mask[0], &mask[1], &mask[2],
&mask[3], &mask[4], &mask[5]);
if (i > currmax)
currmax = i;
break;
switch (opt) {
case 'm':
i = sscanf(optarg, "%x,%x,%x,%x,%x,%x",
&mask[0], &mask[1], &mask[2],
&mask[3], &mask[4], &mask[5]);
if (i > currmax)
currmax = i;
break;
case 'v':
i = sscanf(optarg, "%x,%x,%x,%x,%x,%x",
&value[0], &value[1], &value[2],
&value[3], &value[4], &value[5]);
if (i > currmax)
currmax = i;
break;
case 'v':
i = sscanf(optarg, "%x,%x,%x,%x,%x,%x",
&value[0], &value[1], &value[2],
&value[3], &value[4], &value[5]);
if (i > currmax)
currmax = i;
break;
case 'i':
i = sscanf(optarg, "%d,%d,%d,%d,%d,%d",
&inv_filter[0], &inv_filter[1], &inv_filter[2],
&inv_filter[3], &inv_filter[4], &inv_filter[5]);
if (i > currmax)
currmax = i;
break;
case 'i':
i = sscanf(optarg, "%d,%d,%d,%d,%d,%d",
&inv_filter[0], &inv_filter[1], &inv_filter[2],
&inv_filter[3], &inv_filter[4], &inv_filter[5]);
if (i > currmax)
currmax = i;
break;
case 'e':
i = sscanf(optarg, "%x,%x,%x,%x,%x,%x",
&err_mask[0], &err_mask[1], &err_mask[2],
&err_mask[3], &err_mask[4], &err_mask[5]);
if (i > currmax)
currmax = i;
break;
case 'p':
port = atoi(optarg);
break;
default:
print_usage(basename(argv[0]));
exit(1);
break;
case 'e':
i = sscanf(optarg, "%x,%x,%x,%x,%x,%x",
&err_mask[0], &err_mask[1], &err_mask[2],
&err_mask[3], &err_mask[4], &err_mask[5]);
if (i > currmax)
currmax = i;
break;
case 'p':
port = atoi(optarg);
break;
default:
print_usage(basename(argv[0]));
exit(1);
break;
}
}
}
if (optind == argc) {
print_usage(basename(argv[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);
if (optind == argc) {
print_usage(basename(argv[0]));
exit(0);
}
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
printf("open %d '%s' m%08X v%08X i%d e%d.\n",
i, argv[optind+i], mask[i], value[i],
inv_filter[i], err_mask[i]);
printf("open %d '%s' m%08X v%08X i%d e%d.\n",
i, argv[optind+i], mask[i], value[i],
inv_filter[i], err_mask[i]);
#endif
if ((s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
perror("socket");
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 ((s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
perror("socket");
return 1;
}
if (nbytes < sizeof(struct can_frame)) {
fprintf(stderr, "read: incomplete CAN frame\n");
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 (ioctl(s[i], SIOCGSTAMP, &tv) < 0)
perror("SIOCGSTAMP");
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]);
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;
if (!(j < IFNAMSIZ)) {
printf("name of CAN device '%s' is too long!\n", argv[optind+i]);
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
/* 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);
/* 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);
#endif
}
}
}
}
}
for (i=0; i<currmax; i++)
close(s[i]);
for (i=0; i<currmax; i++)
close(s[i]);
close(accsocket);
return 0;
close(accsocket);
return 0;
}

View File

@ -66,9 +66,9 @@
#define BUFSZ 100 /* for one line in the logfile */
struct assignment {
char txif[IFNAMSIZ];
int txifidx;
char rxif[IFNAMSIZ];
char txif[IFNAMSIZ];
int txifidx;
char rxif[IFNAMSIZ];
};
static struct assignment asgn[CHANNELS];
@ -76,28 +76,28 @@ extern int optind, opterr, optopt;
void print_usage(char *prg)
{
fprintf(stderr, "\nUsage: %s <options> [interface assignment]*\n\n", prg);
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
fprintf(stderr, " -l <num> "
"(process input file <num> times)\n"
" "
"(Use 'i' for infinite loop - default: %d)\n", DEFAULT_LOOPS);
fprintf(stderr, " -t (ignore timestamps: "
"send frames immediately)\n");
fprintf(stderr, " -g <ms> (gap in milli "
"seconds - default: %d ms)\n", DEFAULT_GAP);
fprintf(stderr, " -s <s> (skip gaps in "
"timestamps > 's' seconds)\n");
fprintf(stderr, " -x (disable local "
"loopback of sent CAN frames)\n");
fprintf(stderr, " -v (verbose: print "
"sent CAN frames)\n\n");
fprintf(stderr, "Interface assignment: 0..n assignments like "
"<write-if>=<log-if>\n");
fprintf(stderr, "e.g. vcan2=can0 ( send frames received from can0 on "
"vcan2 )\n");
fprintf(stderr, "No assignments => send frames to the interface(s) they "
"had been received from.\n\n");
fprintf(stderr, "\nUsage: %s <options> [interface assignment]*\n\n", prg);
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
fprintf(stderr, " -l <num> "
"(process input file <num> times)\n"
" "
"(Use 'i' for infinite loop - default: %d)\n", DEFAULT_LOOPS);
fprintf(stderr, " -t (ignore timestamps: "
"send frames immediately)\n");
fprintf(stderr, " -g <ms> (gap in milli "
"seconds - default: %d ms)\n", DEFAULT_GAP);
fprintf(stderr, " -s <s> (skip gaps in "
"timestamps > 's' seconds)\n");
fprintf(stderr, " -x (disable local "
"loopback of sent CAN frames)\n");
fprintf(stderr, " -v (verbose: print "
"sent CAN frames)\n\n");
fprintf(stderr, "Interface assignment: 0..n assignments like "
"<write-if>=<log-if>\n");
fprintf(stderr, "e.g. vcan2=can0 ( send frames received from can0 on "
"vcan2 )\n");
fprintf(stderr, "No assignments => send frames to the interface(s) they "
"had been received from.\n\n");
}
/* 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)
{
if (lhs->tv_sec < rhs->tv_sec)
return -1;
if (lhs->tv_sec > rhs->tv_sec)
return 1;
return lhs->tv_usec - rhs->tv_usec;
if (lhs->tv_sec < rhs->tv_sec)
return -1;
if (lhs->tv_sec > rhs->tv_sec)
return 1;
return lhs->tv_usec - rhs->tv_usec;
}
static inline void create_diff_tv(struct timeval *today, struct timeval *diff,
struct timeval *log) {
/* create diff_tv so that log_tv + diff_tv = today_tv */
diff->tv_sec = today->tv_sec - log->tv_sec;
diff->tv_usec = today->tv_usec - log->tv_usec;
/* create diff_tv so that log_tv + diff_tv = today_tv */
diff->tv_sec = today->tv_sec - log->tv_sec;
diff->tv_usec = today->tv_usec - log->tv_usec;
}
static inline int frames_to_send(struct timeval *today, struct timeval *diff,
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_usec = log->tv_usec + diff->tv_usec;
cmp.tv_sec = log->tv_sec + diff->tv_sec;
cmp.tv_usec = log->tv_usec + diff->tv_usec;
if (cmp.tv_usec > 1000000) {
cmp.tv_usec -= 1000000;
cmp.tv_sec++;
}
if (cmp.tv_usec > 1000000) {
cmp.tv_usec -= 1000000;
cmp.tv_sec++;
}
if (cmp.tv_usec < 0) {
cmp.tv_usec += 1000000;
cmp.tv_sec--;
}
if (cmp.tv_usec < 0) {
cmp.tv_usec += 1000000;
cmp.tv_sec--;
}
return timeval_compare(&cmp, today);
return timeval_compare(&cmp, today);
}
int get_txidx(char *logif_name) {
int i;
int i;
for (i=0; i<CHANNELS; i++) {
if (asgn[i].rxif[0] == 0) /* end of table content */
break;
if (strcmp(asgn[i].rxif, logif_name) == 0) /* found device name */
break;
}
for (i=0; i<CHANNELS; i++) {
if (asgn[i].rxif[0] == 0) /* end of table content */
break;
if (strcmp(asgn[i].rxif, logif_name) == 0) /* found device name */
break;
}
if ((i == CHANNELS) || (asgn[i].rxif[0] == 0))
return 0; /* not found */
if ((i == CHANNELS) || (asgn[i].rxif[0] == 0))
return 0; /* not found */
return asgn[i].txifidx; /* return interface index */
return asgn[i].txifidx; /* return interface index */
}
char *get_txname(char *logif_name) {
int i;
int i;
for (i=0; i<CHANNELS; i++) {
if (asgn[i].rxif[0] == 0) /* end of table content */
break;
if (strcmp(asgn[i].rxif, logif_name) == 0) /* found device name */
break;
}
for (i=0; i<CHANNELS; i++) {
if (asgn[i].rxif[0] == 0) /* end of table content */
break;
if (strcmp(asgn[i].rxif, logif_name) == 0) /* found device name */
break;
}
if ((i == CHANNELS) || (asgn[i].rxif[0] == 0))
return 0; /* not found */
if ((i == CHANNELS) || (asgn[i].rxif[0] == 0))
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 verbose) {
struct ifreq ifr;
int i;
struct ifreq ifr;
int i;
/* find free entry */
for (i=0; i<CHANNELS; i++) {
if (asgn[i].txif[0] == 0)
break;
}
/* find free entry */
for (i=0; i<CHANNELS; i++) {
if (asgn[i].txif[0] == 0)
break;
}
if (i == CHANNELS) {
fprintf(stderr, "Assignment table exceeded!\n");
return 1;
}
if (i == CHANNELS) {
fprintf(stderr, "Assignment table exceeded!\n");
return 1;
}
if (strlen(txname) >= IFNAMSIZ) {
fprintf(stderr, "write-if interface name '%s' too long!", txname);
return 1;
}
strcpy(asgn[i].txif, txname);
if (strlen(txname) >= IFNAMSIZ) {
fprintf(stderr, "write-if interface name '%s' too long!", txname);
return 1;
}
strcpy(asgn[i].txif, txname);
if (strlen(rxname) >= IFNAMSIZ) {
fprintf(stderr, "log-if interface name '%s' too long!", rxname);
return 1;
}
strcpy(asgn[i].rxif, rxname);
if (strlen(rxname) >= IFNAMSIZ) {
fprintf(stderr, "log-if interface name '%s' too long!", rxname);
return 1;
}
strcpy(asgn[i].rxif, rxname);
strcpy(ifr.ifr_name, txname);
if (ioctl(socket, SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX");
fprintf(stderr, "write-if interface name '%s' is wrong!\n", txname);
return 1;
}
asgn[i].txifidx = ifr.ifr_ifindex;
strcpy(ifr.ifr_name, txname);
if (ioctl(socket, SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX");
fprintf(stderr, "write-if interface name '%s' is wrong!\n", txname);
return 1;
}
asgn[i].txifidx = ifr.ifr_ifindex;
if (verbose > 1) /* use -v -v to see this */
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);
if (verbose > 1) /* use -v -v to see this */
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);
return 0;
return 0;
}
int main(int argc, char **argv)
{
static char buf[BUFSZ], device[BUFSZ], ascframe[BUFSZ];
struct sockaddr_can addr;
static struct can_frame frame;
static struct timeval today_tv, log_tv, last_log_tv, diff_tv;
struct timespec sleep_ts;
int s; /* CAN_RAW socket */
FILE *infile = stdin;
unsigned long gap = DEFAULT_GAP;
int use_timestamps = 1;
static int verbose, opt, delay_loops, skipgap;
static int loopback_disable = 0;
static int infinite_loops = 0;
static int loops = DEFAULT_LOOPS;
int assignments; /* assignments defined on the commandline */
int txidx; /* sendto() interface index */
int eof, nbytes, i, j;
static char buf[BUFSZ], device[BUFSZ], ascframe[BUFSZ];
struct sockaddr_can addr;
static struct can_frame frame;
static struct timeval today_tv, log_tv, last_log_tv, diff_tv;
struct timespec sleep_ts;
int s; /* CAN_RAW socket */
FILE *infile = stdin;
unsigned long gap = DEFAULT_GAP;
int use_timestamps = 1;
static int verbose, opt, delay_loops, skipgap;
static int loopback_disable = 0;
static int infinite_loops = 0;
static int loops = DEFAULT_LOOPS;
int assignments; /* assignments defined on the commandline */
int txidx; /* sendto() interface index */
int eof, nbytes, i, j;
while ((opt = getopt(argc, argv, "I:l:tg:s:xv")) != -1) {
switch (opt) {
case 'I':
infile = fopen(optarg, "r");
if (!infile) {
perror("infile");
return 1;
}
break;
while ((opt = getopt(argc, argv, "I:l:tg:s:xv")) != -1) {
switch (opt) {
case 'I':
infile = fopen(optarg, "r");
if (!infile) {
perror("infile");
return 1;
}
break;
case 'l':
if (optarg[0] == 'i')
infinite_loops = 1;
else
if (!(loops = atoi(optarg))) {
fprintf(stderr, "Invalid argument for option -l !\n");
return 1;
case 'l':
if (optarg[0] == 'i')
infinite_loops = 1;
else
if (!(loops = atoi(optarg))) {
fprintf(stderr, "Invalid argument for option -l !\n");
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 */
infinite_loops = 0;
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;
if (infile == stdin) { /* no jokes with stdin */
infinite_loops = 0;
loops = 1;
}
}
while (infinite_loops || loops--) {
if (infile != stdin)
rewind(infile); /* for each loop */
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 */
goto out; /* nothing to read */
sleep_ts.tv_sec = gap / 1000;
sleep_ts.tv_nsec = (gap % 1000) * 1000000;
eof = 0;
if (sscanf(buf, "(%ld.%ld) %s %s", &log_tv.tv_sec, &log_tv.tv_usec,
device, ascframe) != 4)
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;
/* open socket */
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
perror("socket");
return 1;
}
while (!eof) {
addr.can_family = AF_CAN;
addr.can_ifindex = 0;
while ((!use_timestamps) ||
(frames_to_send(&today_tv, &diff_tv, &log_tv) < 0)) {
/* disable unneeded default receive filter on this RAW socket */
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) {
fprintf(stderr, "log interface name '%s' too long!", device);
return 1;
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;
}
}
txidx = get_txidx(device); /* get ifindex for sending the frame */
while (infinite_loops || loops--) {
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);
}
if (infile != stdin)
rewind(infile); /* for each loop */
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)) {
fprintf(stderr, "wrong CAN frame format: '%s'!", ascframe);
return 1;
}
if (!fgets(buf, BUFSZ-1, infile)) /* read first frame from logfile */
goto out; /* nothing to read */
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;
}
eof = 0;
if (sscanf(buf, "(%ld.%ld) %s %s", &log_tv.tv_sec, &log_tv.tv_usec,
device, ascframe) != 4)
return 1;
return 1;
if (use_timestamps) {
gettimeofday(&today_tv, NULL);
if (use_timestamps) { /* throttle sending due to logfile timestamps */
/* 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))
gettimeofday(&today_tv, NULL);
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))
return 1;
while ((!use_timestamps) ||
(frames_to_send(&today_tv, &diff_tv, &log_tv) < 0)) {
delay_loops++; /* private statistics */
gettimeofday(&today_tv, NULL);
/* log_tv/device/ascframe are valid here */
} /* 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);
fclose(infile);
if (txidx) { /* only send to valid CAN devices */
if (verbose > 1) /* use -v -v to see this */
printf("%d delay_loops\n", delay_loops);
if (parse_canframe(ascframe, &frame)) {
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 s; /* can raw socket */
int nbytes;
struct sockaddr_can addr;
struct can_frame frame;
struct ifreq ifr;
int s; /* can raw socket */
int nbytes;
struct sockaddr_can addr;
struct can_frame frame;
struct ifreq ifr;
/* check command line options */
if (argc != 3) {
fprintf(stderr, "Usage: %s <device> <can_frame>.\n", argv[0]);
return 1;
}
/* check command line options */
if (argc != 3) {
fprintf(stderr, "Usage: %s <device> <can_frame>.\n", argv[0]);
return 1;
}
/* parse CAN frame */
if (parse_canframe(argv[2], &frame)){
fprintf(stderr, "\nWrong CAN-frame format!\n\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, "data has 0 to 8 hex-values that can (optionally)");
fprintf(stderr, " be seperated by '.'\n\n");
fprintf(stderr, "e.g. 5A1#11.2233.44556677.88 / 123#DEADBEEF / ");
fprintf(stderr, "5AA# /\n 1F334455#1122334455667788 / 123#R ");
fprintf(stderr, "for remote transmission request.\n\n");
return 1;
}
/* parse CAN frame */
if (parse_canframe(argv[2], &frame)){
fprintf(stderr, "\nWrong CAN-frame format!\n\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, "data has 0 to 8 hex-values that can (optionally)");
fprintf(stderr, " be seperated by '.'\n\n");
fprintf(stderr, "e.g. 5A1#11.2233.44556677.88 / 123#DEADBEEF / ");
fprintf(stderr, "5AA# /\n 1F334455#1122334455667788 / 123#R ");
fprintf(stderr, "for remote transmission request.\n\n");
return 1;
}
/* open socket */
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
perror("socket");
return 1;
}
/* open socket */
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
perror("socket");
return 1;
}
addr.can_family = AF_CAN;
addr.can_family = AF_CAN;
strcpy(ifr.ifr_name, argv[1]);
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX");
return 1;
}
addr.can_ifindex = ifr.ifr_ifindex;
strcpy(ifr.ifr_name, argv[1]);
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);
/* 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 (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind");
return 1;
}
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind");
return 1;
}
/* send frame */
if ((nbytes = write(s, &frame, sizeof(frame))) != sizeof(frame)) {
perror("write");
return 1;
}
/* send frame */
if ((nbytes = write(s, &frame, sizeof(frame))) != sizeof(frame)) {
perror("write");
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) {
if ((c >= '0') && (c <= '9'))
return c - '0';
if ((c >= '0') && (c <= '9'))
return c - '0';
if ((c >= 'A') && (c <= 'F'))
return c - 'A' + 10;
if ((c >= 'A') && (c <= 'F'))
return c - 'A' + 10;
if ((c >= 'a') && (c <= 'f'))
return c - 'a' + 10;
if ((c >= 'a') && (c <= 'f'))
return c - 'a' + 10;
return 16; /* error */
return 16; /* error */
}
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);
//printf("'%s' len %d\n", cs, len);
len = strlen(cs);
//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)
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)
if (len < 4)
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)
if (!((cs[3] == CANID_DELIM) || (cs[8] == CANID_DELIM)))
return 1;
cf->can_id |= (tmp << (2-i)*4);
}
}
if((cs[idx] == 'R') || (cs[idx] == 'r')){ /* RTR frame */
cf->can_id |= CAN_RTR_FLAG;
if (cs[8] == CANID_DELIM) { /* 8 digits */
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;
}
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) {
/* 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);
fprintf(stream, "%s", buf);
if (eol)
fprintf(stream, "%s", eol);
sprint_canframe(buf, cf, sep);
fprintf(stream, "%s", buf);
if (eol)
fprintf(stream, "%s", eol);
}
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) {
sprintf(buf, "%08X#", cf->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG));
offset = 9;
} else if (cf->can_id & CAN_EFF_FLAG) {
sprintf(buf, "%08X#", cf->can_id & CAN_EFF_MASK);
offset = 9;
} else {
sprintf(buf, "%03X#", cf->can_id & CAN_SFF_MASK);
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_ERR_FLAG) {
sprintf(buf, "%08X#", cf->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG));
offset = 9;
} else if (cf->can_id & CAN_EFF_FLAG) {
sprintf(buf, "%08X#", cf->can_id & CAN_EFF_MASK);
offset = 9;
} else {
sprintf(buf, "%03X#", cf->can_id & CAN_SFF_MASK);
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++, ".");
}
}
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);
fprintf(stream, "%s", buf);
if (eol)
fprintf(stream, "%s", eol);
sprint_long_canframe(buf, cf, view);
fprintf(stream, "%s", buf);
if (eol)
fprintf(stream, "%s", eol);
}
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) {
sprintf(buf, "%8X ", cf->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG));
offset = 10;
} else if (cf->can_id & CAN_EFF_FLAG) {
sprintf(buf, "%8X ", cf->can_id & CAN_EFF_MASK);
offset = 10;
} else {
sprintf(buf, "%3X ", cf->can_id & CAN_SFF_MASK);
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';
if (cf->can_id & CAN_ERR_FLAG) {
sprintf(buf, "%8X ", cf->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG));
offset = 10;
} else if (cf->can_id & CAN_EFF_FLAG) {
sprintf(buf, "%8X ", cf->can_id & CAN_EFF_MASK);
offset = 10;
} else {
sprintf(buf, "%3X ", cf->can_id & CAN_SFF_MASK);
offset = 5;
}
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;
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 (cf->can_id & CAN_ERR_FLAG)
sprintf(buf+offset, "%*s", dlen*(8-cf->can_dlc)+13, "ERRORFRAME");
else if (view & CANLIB_VIEW_ASCII) {
j = dlen*(8-cf->can_dlc)+4;
sprintf(buf+offset, "%*s", j, "'");
offset += j;
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 {
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->data[i] > 0x1F) && (cf->data[i] < 0x7F))
buf[offset++] = cf->data[i];
else
buf[offset++] = '.';
if (cf->can_id & CAN_ERR_FLAG)
sprintf(buf+offset, "%*s", dlen*(8-cf->can_dlc)+13, "ERRORFRAME");
else if (view & CANLIB_VIEW_ASCII) {
j = dlen*(8-cf->can_dlc)+4;
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)
{
fprintf(stderr, "Usage: %s [can-interfaces]\n", prg);
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
fprintf(stderr, " -O <outfile> (default stdout)\n");
fprintf(stderr, " -4 (reduce decimal place to 4 digits)\n");
fprintf(stderr, " -n (set newline to cr/lf - default lf)\n");
fprintf(stderr, "Usage: %s [can-interfaces]\n", prg);
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
fprintf(stderr, " -O <outfile> (default stdout)\n");
fprintf(stderr, " -4 (reduce decimal place to 4 digits)\n");
fprintf(stderr, " -n (set newline to cr/lf - default lf)\n");
}
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;
static struct timeval tv, start_tv;
FILE *infile = stdin;
FILE *outfile = stdout;
static int maxdev, devno, i, crlf, d4, opt;
struct can_frame cf;
static struct timeval tv, start_tv;
FILE *infile = stdin;
FILE *outfile = stdout;
static int maxdev, devno, i, crlf, d4, opt;
while ((opt = getopt(argc, argv, "I:O:4n")) != -1) {
switch (opt) {
case 'I':
infile = fopen(optarg, "r");
if (!infile) {
perror("infile");
return 1;
}
break;
while ((opt = getopt(argc, argv, "I:O:4n")) != -1) {
switch (opt) {
case 'I':
infile = fopen(optarg, "r");
if (!infile) {
perror("infile");
return 1;
}
break;
case 'O':
outfile = fopen(optarg, "w");
if (!outfile) {
perror("outfile");
return 1;
}
break;
case 'O':
outfile = fopen(optarg, "w");
if (!outfile) {
perror("outfile");
return 1;
}
break;
case 'n':
crlf = 1;
break;
case 'n':
crlf = 1;
break;
case '4':
d4 = 1;
break;
case '4':
d4 = 1;
break;
default:
fprintf(stderr, "Unknown option %c\n", opt);
print_usage(basename(argv[0]));
return 1;
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]);
}
default:
fprintf(stderr, "Unknown option %c\n", opt);
print_usage(basename(argv[0]));
return 1;
break;
}
}
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)
{
char buf[100], timestamp[100], device[100], ascframe[100];
struct can_frame cf;
char buf[100], timestamp[100], device[100], ascframe[100];
struct can_frame cf;
while (fgets(buf, 99, stdin)) {
if (sscanf(buf, "%s %s %s", timestamp, device, ascframe) != 3)
return 1;
if (parse_canframe(ascframe, &cf))
return 1;
sprint_long_canframe(ascframe, &cf, 1); /* with ASCII output */
printf("%s %s %s\n", timestamp, device, ascframe);
}
while (fgets(buf, 99, stdin)) {
if (sscanf(buf, "%s %s %s", timestamp, device, ascframe) != 3)
return 1;
if (parse_canframe(ascframe, &cf))
return 1;
sprint_long_canframe(ascframe, &cf, 1); /* with ASCII output */
printf("%s %s %s\n", timestamp, device, ascframe);
}
return 0;
return 0;
}

154
vcan.c
View File

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