Whitespace fixes. Indented the code following Linux styleguide to fix
the mess between tabs and spaces.pull/7/head
parent
8a5c0365e6
commit
adbe6f9bee
424
asc2log.c
424
asc2log.c
|
|
@ -65,272 +65,272 @@ extern int optind, opterr, optopt;
|
||||||
|
|
||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: %s\n", prg);
|
fprintf(stderr, "Usage: %s\n", prg);
|
||||||
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
|
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
|
||||||
fprintf(stderr, " -O <outfile> (default stdout)\n");
|
fprintf(stderr, " -O <outfile> (default stdout)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void prframe(FILE *file, struct timeval *tv, int dev, struct can_frame *cf) {
|
void prframe(FILE *file, struct timeval *tv, int dev, struct can_frame *cf) {
|
||||||
|
|
||||||
fprintf(file, "(%ld.%06ld) ", tv->tv_sec, tv->tv_usec);
|
fprintf(file, "(%ld.%06ld) ", tv->tv_sec, tv->tv_usec);
|
||||||
if (dev > 0)
|
if (dev > 0)
|
||||||
fprintf(file, "can%d ", dev-1);
|
fprintf(file, "can%d ", dev-1);
|
||||||
else
|
else
|
||||||
fprintf(file, "canX ");
|
fprintf(file, "canX ");
|
||||||
fprint_canframe(file, cf, "\n", 0);
|
fprint_canframe(file, cf, "\n", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_can_id(struct can_frame *cf, char *idstring, int base) {
|
void get_can_id(struct can_frame *cf, char *idstring, int base) {
|
||||||
|
|
||||||
if (idstring[strlen(idstring)-1] == 'x') {
|
if (idstring[strlen(idstring)-1] == 'x') {
|
||||||
cf->can_id = CAN_EFF_FLAG;
|
cf->can_id = CAN_EFF_FLAG;
|
||||||
idstring[strlen(idstring)-1] = 0;
|
idstring[strlen(idstring)-1] = 0;
|
||||||
} else
|
} else
|
||||||
cf->can_id = 0;
|
cf->can_id = 0;
|
||||||
|
|
||||||
cf->can_id |= strtoul(idstring, NULL, base);
|
cf->can_id |= strtoul(idstring, NULL, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
void calc_tv(struct timeval *tv, struct timeval *read_tv,
|
void calc_tv(struct timeval *tv, struct timeval *read_tv,
|
||||||
struct timeval *date_tv, char timestamps, int dplace) {
|
struct timeval *date_tv, char timestamps, int dplace) {
|
||||||
|
|
||||||
if (dplace == 4) /* shift values having only 4 decimal places */
|
if (dplace == 4) /* shift values having only 4 decimal places */
|
||||||
read_tv->tv_usec *= 100; /* and need for 6 */
|
read_tv->tv_usec *= 100; /* and need for 6 */
|
||||||
|
|
||||||
if (timestamps == 'a') { /* absolute */
|
if (timestamps == 'a') { /* absolute */
|
||||||
|
|
||||||
tv->tv_sec = date_tv->tv_sec + read_tv->tv_sec;
|
tv->tv_sec = date_tv->tv_sec + read_tv->tv_sec;
|
||||||
tv->tv_usec = date_tv->tv_usec + read_tv->tv_usec;
|
tv->tv_usec = date_tv->tv_usec + read_tv->tv_usec;
|
||||||
|
|
||||||
} else { /* relative */
|
} else { /* relative */
|
||||||
|
|
||||||
if (((!tv->tv_sec) && (!tv->tv_usec)) &&
|
if (((!tv->tv_sec) && (!tv->tv_usec)) &&
|
||||||
(date_tv->tv_sec || date_tv->tv_usec)) {
|
(date_tv->tv_sec || date_tv->tv_usec)) {
|
||||||
tv->tv_sec = date_tv->tv_sec; /* initial date/time */
|
tv->tv_sec = date_tv->tv_sec; /* initial date/time */
|
||||||
tv->tv_usec = date_tv->tv_usec;
|
tv->tv_usec = date_tv->tv_usec;
|
||||||
|
}
|
||||||
|
|
||||||
|
tv->tv_sec += read_tv->tv_sec;
|
||||||
|
tv->tv_usec += read_tv->tv_usec;
|
||||||
}
|
}
|
||||||
|
|
||||||
tv->tv_sec += read_tv->tv_sec;
|
if (tv->tv_usec > 1000000) {
|
||||||
tv->tv_usec += read_tv->tv_usec;
|
tv->tv_usec -= 1000000;
|
||||||
}
|
tv->tv_sec++;
|
||||||
|
}
|
||||||
if (tv->tv_usec > 1000000) {
|
|
||||||
tv->tv_usec -= 1000000;
|
|
||||||
tv->tv_sec++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_date(struct timeval *tv, char *date) {
|
int get_date(struct timeval *tv, char *date) {
|
||||||
|
|
||||||
char ctmp[10];
|
char ctmp[10];
|
||||||
int itmp;
|
int itmp;
|
||||||
|
|
||||||
struct tm tms;
|
struct tm tms;
|
||||||
|
|
||||||
if (sscanf(date, "%9s %d %9s %9s %d", ctmp, &itmp, ctmp, ctmp, &itmp) == 5) {
|
if (sscanf(date, "%9s %d %9s %9s %d", ctmp, &itmp, ctmp, ctmp, &itmp) == 5) {
|
||||||
/* assume EN/US date due to existing am/pm field */
|
/* assume EN/US date due to existing am/pm field */
|
||||||
|
|
||||||
if (!setlocale(LC_TIME, "en_US"))
|
if (!setlocale(LC_TIME, "en_US"))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!strptime(date, "%B %d %r %Y", &tms))
|
if (!strptime(date, "%B %d %r %Y", &tms))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* assume DE date due to non existing am/pm field */
|
/* assume DE date due to non existing am/pm field */
|
||||||
|
|
||||||
if (sscanf(date, "%9s %d %9s %d", ctmp, &itmp, ctmp, &itmp) != 4)
|
if (sscanf(date, "%9s %d %9s %d", ctmp, &itmp, ctmp, &itmp) != 4)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!setlocale(LC_TIME, "de_DE"))
|
if (!setlocale(LC_TIME, "de_DE"))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!strptime(date, "%B %d %T %Y", &tms))
|
if (!strptime(date, "%B %d %T %Y", &tms))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//printf("h %d m %d s %d d %d m %d y %d\n",
|
//printf("h %d m %d s %d d %d m %d y %d\n",
|
||||||
//tms.tm_hour, tms.tm_min, tms.tm_sec,
|
//tms.tm_hour, tms.tm_min, tms.tm_sec,
|
||||||
//tms.tm_mday, tms.tm_mon+1, tms.tm_year+1900);
|
//tms.tm_mday, tms.tm_mon+1, tms.tm_year+1900);
|
||||||
|
|
||||||
tv->tv_sec = mktime(&tms);
|
tv->tv_sec = mktime(&tms);
|
||||||
|
|
||||||
if (tv->tv_sec < 0)
|
if (tv->tv_sec < 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char buf[100], tmp1[100], tmp2[100];
|
char buf[100], tmp1[100], tmp2[100];
|
||||||
|
|
||||||
FILE *infile = stdin;
|
FILE *infile = stdin;
|
||||||
FILE *outfile = stdout;
|
FILE *outfile = stdout;
|
||||||
static int verbose;
|
static int verbose;
|
||||||
struct can_frame cf;
|
struct can_frame cf;
|
||||||
static struct timeval tv; /* current frame timestamp */
|
static struct timeval tv; /* current frame timestamp */
|
||||||
static struct timeval read_tv; /* frame timestamp from ASC file */
|
static struct timeval read_tv; /* frame timestamp from ASC file */
|
||||||
static struct timeval date_tv; /* date of the ASC file */
|
static struct timeval date_tv; /* date of the ASC file */
|
||||||
static int dplace; /* decimal place 4 or 6 or uninitialized */
|
static int dplace; /* decimal place 4 or 6 or uninitialized */
|
||||||
static char base; /* 'd'ec or 'h'ex */
|
static char base; /* 'd'ec or 'h'ex */
|
||||||
static char timestamps; /* 'a'bsolute or 'r'elative */
|
static char timestamps; /* 'a'bsolute or 'r'elative */
|
||||||
|
|
||||||
int interface;
|
int interface;
|
||||||
char rtr;
|
char rtr;
|
||||||
int dlc = 0;
|
int dlc = 0;
|
||||||
int data[8];
|
int data[8];
|
||||||
int i, found, opt;
|
int i, found, opt;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "I:O:v")) != -1) {
|
while ((opt = getopt(argc, argv, "I:O:v")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'I':
|
case 'I':
|
||||||
infile = fopen(optarg, "r");
|
infile = fopen(optarg, "r");
|
||||||
if (!infile) {
|
if (!infile) {
|
||||||
perror("infile");
|
perror("infile");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'O':
|
case 'O':
|
||||||
outfile = fopen(optarg, "w");
|
outfile = fopen(optarg, "w");
|
||||||
if (!outfile) {
|
if (!outfile) {
|
||||||
perror("outfile");
|
perror("outfile");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'v':
|
case 'v':
|
||||||
verbose = 1;
|
verbose = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Unknown option %c\n", opt);
|
fprintf(stderr, "Unknown option %c\n", opt);
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
while (fgets(buf, 99, infile)) {
|
|
||||||
|
|
||||||
if (!dplace) { /* the representation of a valid CAN frame not known */
|
|
||||||
|
|
||||||
/* check for base and timestamp entries in the header */
|
|
||||||
if ((!base) &&
|
|
||||||
(sscanf(buf, "base %s timestamps %s", tmp1, tmp2) == 2)) {
|
|
||||||
base = tmp1[0];
|
|
||||||
timestamps = tmp2[0];
|
|
||||||
if (verbose)
|
|
||||||
printf("base %c timestamps %c\n", base, timestamps);
|
|
||||||
if ((base != 'h') && (base != 'd')) {
|
|
||||||
printf("invalid base %s (must be 'hex' or 'dez')!\n",
|
|
||||||
tmp1);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
if ((timestamps != 'a') && (timestamps != 'r')) {
|
|
||||||
printf("invalid timestamps %s (must be 'absolute'"
|
|
||||||
" or 'relative')!\n", tmp2);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
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 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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')
|
while (fgets(buf, 99, infile)) {
|
||||||
cf.can_id |= CAN_RTR_FLAG;
|
|
||||||
|
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 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
cf.can_dlc = dlc & 0x0FU;
|
||||||
for (i=0; i<dlc; i++)
|
for (i=0; i<dlc; i++)
|
||||||
cf.data[i] = data[i] & 0xFFU;
|
cf.data[i] = data[i] & 0xFFU;
|
||||||
|
|
||||||
calc_tv(&tv, &read_tv, &date_tv, timestamps, dplace);
|
calc_tv(&tv, &read_tv, &date_tv, timestamps, dplace);
|
||||||
prframe(outfile, &tv, interface, &cf);
|
prframe(outfile, &tv, interface, &cf);
|
||||||
fflush(outfile);
|
fflush(outfile);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for ErrorFrames */
|
/* check for ErrorFrames */
|
||||||
if (sscanf(buf, "%ld.%ld %d %s",
|
if (sscanf(buf, "%ld.%ld %d %s",
|
||||||
&read_tv.tv_sec, &read_tv.tv_usec,
|
&read_tv.tv_sec, &read_tv.tv_usec,
|
||||||
&interface, tmp1) == 4) {
|
&interface, tmp1) == 4) {
|
||||||
|
|
||||||
if (!strncmp(tmp1, "ErrorFrame", strlen("ErrorFrame"))) {
|
if (!strncmp(tmp1, "ErrorFrame", strlen("ErrorFrame"))) {
|
||||||
|
|
||||||
memset(&cf, 0, sizeof(cf));
|
memset(&cf, 0, sizeof(cf));
|
||||||
/* do not know more than 'Error' */
|
/* do not know more than 'Error' */
|
||||||
cf.can_id = (CAN_ERR_FLAG | CAN_ERR_BUSERROR);
|
cf.can_id = (CAN_ERR_FLAG | CAN_ERR_BUSERROR);
|
||||||
cf.can_dlc = CAN_ERR_DLC;
|
cf.can_dlc = CAN_ERR_DLC;
|
||||||
|
|
||||||
calc_tv(&tv, &read_tv, &date_tv, timestamps, dplace);
|
calc_tv(&tv, &read_tv, &date_tv, timestamps, dplace);
|
||||||
prframe(outfile, &tv, interface, &cf);
|
prframe(outfile, &tv, interface, &cf);
|
||||||
fflush(outfile);
|
fflush(outfile);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
fclose(outfile);
|
||||||
fclose(outfile);
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
452
canbusload.c
452
canbusload.c
|
|
@ -74,11 +74,11 @@
|
||||||
extern int optind, opterr, optopt;
|
extern int optind, opterr, optopt;
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
char devname[IFNAMSIZ+1];
|
char devname[IFNAMSIZ+1];
|
||||||
unsigned int bitrate;
|
unsigned int bitrate;
|
||||||
unsigned int recv_frames;
|
unsigned int recv_frames;
|
||||||
unsigned int recv_bits_total;
|
unsigned int recv_bits_total;
|
||||||
unsigned int recv_bits_payload;
|
unsigned int recv_bits_payload;
|
||||||
} stat[MAXSOCK+1];
|
} stat[MAXSOCK+1];
|
||||||
|
|
||||||
static int max_devname_len; /* to prevent frazzled device name output */
|
static int max_devname_len; /* to prevent frazzled device name output */
|
||||||
|
|
@ -92,289 +92,289 @@ static char *prg;
|
||||||
|
|
||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
|
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
|
||||||
fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg);
|
fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg);
|
||||||
fprintf(stderr, "Options: -t (show current time on the first line)\n");
|
fprintf(stderr, "Options: -t (show current time on the first line)\n");
|
||||||
fprintf(stderr, " -c (colorize lines)\n");
|
fprintf(stderr, " -c (colorize lines)\n");
|
||||||
fprintf(stderr, " -b (show bargraph in %d%% resolution)\n", PERCENTRES);
|
fprintf(stderr, " -b (show bargraph in %d%% resolution)\n", PERCENTRES);
|
||||||
fprintf(stderr, " -r (redraw the terminal - similar to top)\n");
|
fprintf(stderr, " -r (redraw the terminal - similar to top)\n");
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "Up to %d CAN interfaces with mandatory bitrate can be specified on the \n", MAXSOCK);
|
fprintf(stderr, "Up to %d CAN interfaces with mandatory bitrate can be specified on the \n", MAXSOCK);
|
||||||
fprintf(stderr, "commandline in the form: <ifname>@<bitrate>\n\n");
|
fprintf(stderr, "commandline in the form: <ifname>@<bitrate>\n\n");
|
||||||
fprintf(stderr, "The bitrate is mandatory as it is needed to know the CAN bus bitrate to\n");
|
fprintf(stderr, "The bitrate is mandatory as it is needed to know the CAN bus bitrate to\n");
|
||||||
fprintf(stderr, "calcultate the bus load percentage based on the received CAN frames.\n");
|
fprintf(stderr, "calcultate the bus load percentage based on the received CAN frames.\n");
|
||||||
fprintf(stderr, "For each given interface the data is presented in one line which contains:\n\n");
|
fprintf(stderr, "For each given interface the data is presented in one line which contains:\n\n");
|
||||||
fprintf(stderr, "(interface) (received CAN frames) (used bits total) (used bits for payload)\n");
|
fprintf(stderr, "(interface) (received CAN frames) (used bits total) (used bits for payload)\n");
|
||||||
fprintf(stderr, "\nExample:\n");
|
fprintf(stderr, "\nExample:\n");
|
||||||
fprintf(stderr, "\nuser$> canbusload can0@100000 can1@500000 can2@500000 can3@500000 -r -t -b -c\n\n");
|
fprintf(stderr, "\nuser$> canbusload can0@100000 can1@500000 can2@500000 can3@500000 -r -t -b -c\n\n");
|
||||||
fprintf(stderr, "%s 2008-05-27 15:18:49\n", prg);
|
fprintf(stderr, "%s 2008-05-27 15:18:49\n", prg);
|
||||||
fprintf(stderr, " can0@100000 805 74491 36656 74%% |XXXXXXXXXXXXXX......|\n");
|
fprintf(stderr, " can0@100000 805 74491 36656 74%% |XXXXXXXXXXXXXX......|\n");
|
||||||
fprintf(stderr, " can1@500000 796 75140 37728 15%% |XXX.................|\n");
|
fprintf(stderr, " can1@500000 796 75140 37728 15%% |XXX.................|\n");
|
||||||
fprintf(stderr, " can2@500000 0 0 0 0%% |....................|\n");
|
fprintf(stderr, " can2@500000 0 0 0 0%% |....................|\n");
|
||||||
fprintf(stderr, " can3@500000 47 4633 2424 0%% |....................|\n");
|
fprintf(stderr, " can3@500000 47 4633 2424 0%% |....................|\n");
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void sigterm(int signo)
|
void sigterm(int signo)
|
||||||
{
|
{
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void printstats(int signo)
|
void printstats(int signo)
|
||||||
{
|
{
|
||||||
int i, j, percent;
|
int i, j, percent;
|
||||||
|
|
||||||
if (redraw)
|
if (redraw)
|
||||||
printf("%s", CSR_HOME);
|
printf("%s", CSR_HOME);
|
||||||
|
|
||||||
if (timestamp) {
|
if (timestamp) {
|
||||||
time_t currtime;
|
time_t currtime;
|
||||||
struct tm now;
|
struct tm now;
|
||||||
|
|
||||||
if (time(&currtime) == (time_t)-1) {
|
if (time(&currtime) == (time_t)-1) {
|
||||||
perror("time");
|
perror("time");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
localtime_r(&currtime, &now);
|
||||||
|
|
||||||
|
printf("%s %04d-%02d-%02d %02d:%02d:%02d\n",
|
||||||
|
prg,
|
||||||
|
now.tm_year + 1900,
|
||||||
|
now.tm_mon + 1,
|
||||||
|
now.tm_mday,
|
||||||
|
now.tm_hour,
|
||||||
|
now.tm_min,
|
||||||
|
now.tm_sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
localtime_r(&currtime, &now);
|
for (i=0; i<currmax; i++) {
|
||||||
|
|
||||||
printf("%s %04d-%02d-%02d %02d:%02d:%02d\n",
|
if (color)
|
||||||
prg,
|
if (i%2)
|
||||||
now.tm_year + 1900,
|
printf("%s", FGRED);
|
||||||
now.tm_mon + 1,
|
else
|
||||||
now.tm_mday,
|
printf("%s", FGBLUE);
|
||||||
now.tm_hour,
|
|
||||||
now.tm_min,
|
|
||||||
now.tm_sec);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<currmax; i++) {
|
if (stat[i].bitrate)
|
||||||
|
percent = (stat[i].recv_bits_total*100)/stat[i].bitrate;
|
||||||
if (color)
|
|
||||||
if (i%2)
|
|
||||||
printf("%s", FGRED);
|
|
||||||
else
|
|
||||||
printf("%s", FGBLUE);
|
|
||||||
|
|
||||||
if (stat[i].bitrate)
|
|
||||||
percent = (stat[i].recv_bits_total*100)/stat[i].bitrate;
|
|
||||||
else
|
|
||||||
percent = 0;
|
|
||||||
|
|
||||||
printf(" %*s@%-*d %4d %6d %6d %3d%%",
|
|
||||||
max_devname_len, stat[i].devname,
|
|
||||||
max_bitrate_len, stat[i].bitrate,
|
|
||||||
stat[i].recv_frames,
|
|
||||||
stat[i].recv_bits_total,
|
|
||||||
stat[i].recv_bits_payload,
|
|
||||||
percent);
|
|
||||||
|
|
||||||
if (bargraph) {
|
|
||||||
|
|
||||||
printf(" |");
|
|
||||||
|
|
||||||
for (j=0; j < NUMBAR; j++){
|
|
||||||
if (j < percent/PERCENTRES)
|
|
||||||
printf("X");
|
|
||||||
else
|
else
|
||||||
printf(".");
|
percent = 0;
|
||||||
}
|
|
||||||
|
printf(" %*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("|");
|
printf("|");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (color)
|
if (color)
|
||||||
printf("%s", ATTRESET);
|
printf("%s", ATTRESET);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
stat[i].recv_frames = 0;
|
||||||
|
stat[i].recv_bits_total = 0;
|
||||||
|
stat[i].recv_bits_payload = 0;
|
||||||
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
stat[i].recv_frames = 0;
|
alarm(1);
|
||||||
stat[i].recv_bits_total = 0;
|
|
||||||
stat[i].recv_bits_payload = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
alarm(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
fd_set rdfs;
|
fd_set rdfs;
|
||||||
int s[MAXSOCK];
|
int s[MAXSOCK];
|
||||||
|
|
||||||
int opt;
|
int opt;
|
||||||
char *ptr, *nptr;
|
char *ptr, *nptr;
|
||||||
struct sockaddr_can addr;
|
struct sockaddr_can addr;
|
||||||
struct can_frame frame;
|
struct can_frame frame;
|
||||||
int nbytes, i;
|
int nbytes, i;
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
sigset_t sigmask, savesigmask;
|
sigset_t sigmask, savesigmask;
|
||||||
|
|
||||||
signal(SIGTERM, sigterm);
|
signal(SIGTERM, sigterm);
|
||||||
signal(SIGHUP, sigterm);
|
signal(SIGHUP, sigterm);
|
||||||
signal(SIGINT, sigterm);
|
signal(SIGINT, sigterm);
|
||||||
|
|
||||||
signal(SIGALRM, printstats);
|
signal(SIGALRM, printstats);
|
||||||
|
|
||||||
prg = basename(argv[0]);
|
prg = basename(argv[0]);
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "rtbch?")) != -1) {
|
while ((opt = getopt(argc, argv, "rtbch?")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'r':
|
case 'r':
|
||||||
redraw = 1;
|
redraw = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
timestamp = 1;
|
timestamp = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'b':
|
case 'b':
|
||||||
bargraph = 1;
|
bargraph = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
color = 1;
|
color = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
print_usage(prg);
|
print_usage(prg);
|
||||||
exit(1);
|
exit(1);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (optind == argc) {
|
if (optind == argc) {
|
||||||
print_usage(prg);
|
print_usage(prg);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
currmax = argc - optind; /* find real number of CAN devices */
|
currmax = argc - optind; /* find real number of CAN devices */
|
||||||
|
|
||||||
if (currmax > MAXSOCK) {
|
if (currmax > MAXSOCK) {
|
||||||
printf("More than %d CAN devices given on commandline!\n", MAXSOCK);
|
printf("More than %d CAN devices given on commandline!\n", MAXSOCK);
|
||||||
return 1;
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i=0; i < currmax; i++) {
|
||||||
|
|
||||||
|
ptr = argv[optind+i];
|
||||||
|
|
||||||
|
nbytes = strlen(ptr);
|
||||||
|
if (nbytes >= IFNAMSIZ+sizeof("@1000000")+1) {
|
||||||
|
printf("name of CAN device '%s' is too long!\n", ptr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("open %d '%s'.\n", i, ptr);
|
printf("open %d '%s'.\n", i, ptr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
||||||
if (s[i] < 0) {
|
if (s[i] < 0) {
|
||||||
perror("socket");
|
perror("socket");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
nptr = strchr(ptr, '@');
|
nptr = strchr(ptr, '@');
|
||||||
|
|
||||||
if (!nptr) {
|
if (!nptr) {
|
||||||
print_usage(prg);
|
print_usage(prg);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
nbytes = nptr - ptr; /* interface name is up the first '@' */
|
nbytes = nptr - ptr; /* interface name is up the first '@' */
|
||||||
|
|
||||||
if (nbytes >= IFNAMSIZ) {
|
if (nbytes >= IFNAMSIZ) {
|
||||||
printf("name of CAN device '%s' is too long!\n", ptr);
|
printf("name of CAN device '%s' is too long!\n", ptr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(stat[i].devname, ptr, nbytes);
|
strncpy(stat[i].devname, ptr, nbytes);
|
||||||
memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
|
memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
|
||||||
strncpy(ifr.ifr_name, ptr, nbytes);
|
strncpy(ifr.ifr_name, ptr, nbytes);
|
||||||
|
|
||||||
if (nbytes > max_devname_len)
|
if (nbytes > max_devname_len)
|
||||||
max_devname_len = nbytes; /* for nice printing */
|
max_devname_len = nbytes; /* for nice printing */
|
||||||
|
|
||||||
stat[i].bitrate = atoi(nptr+1); /* bitrate is placed behind the '@' */
|
stat[i].bitrate = atoi(nptr+1); /* bitrate is placed behind the '@' */
|
||||||
|
|
||||||
if (!stat[i].bitrate || stat[i].bitrate > 1000000) {
|
if (!stat[i].bitrate || stat[i].bitrate > 1000000) {
|
||||||
printf("invalid bitrate for CAN device '%s'!\n", ptr);
|
printf("invalid bitrate for CAN device '%s'!\n", ptr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
nbytes = strlen(nptr+1);
|
nbytes = strlen(nptr+1);
|
||||||
if (nbytes > max_bitrate_len)
|
if (nbytes > max_bitrate_len)
|
||||||
max_bitrate_len = nbytes; /* for nice printing */
|
max_bitrate_len = nbytes; /* for nice printing */
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("using interface name '%s'.\n", ifr.ifr_name);
|
printf("using interface name '%s'.\n", ifr.ifr_name);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
|
if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
|
||||||
perror("SIOCGIFINDEX");
|
perror("SIOCGIFINDEX");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
addr.can_family = AF_CAN;
|
||||||
|
addr.can_ifindex = ifr.ifr_ifindex;
|
||||||
|
|
||||||
|
if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||||
|
perror("bind");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addr.can_family = AF_CAN;
|
alarm(1);
|
||||||
addr.can_ifindex = ifr.ifr_ifindex;
|
|
||||||
|
|
||||||
if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
if (redraw)
|
||||||
perror("bind");
|
printf("%s", CLR_SCREEN);
|
||||||
return 1;
|
|
||||||
|
while (1) {
|
||||||
|
|
||||||
|
FD_ZERO(&rdfs);
|
||||||
|
for (i=0; i<currmax; i++)
|
||||||
|
FD_SET(s[i], &rdfs);
|
||||||
|
|
||||||
|
savesigmask = sigmask;
|
||||||
|
|
||||||
|
if (pselect(s[currmax-1]+1, &rdfs, NULL, NULL, NULL, &sigmask) < 0) {
|
||||||
|
//perror("pselect");
|
||||||
|
sigmask = savesigmask;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i<currmax; i++) { /* check all CAN RAW sockets */
|
||||||
|
|
||||||
|
if (FD_ISSET(s[i], &rdfs)) {
|
||||||
|
|
||||||
|
nbytes = read(s[i], &frame, sizeof(struct can_frame));
|
||||||
|
|
||||||
|
if (nbytes < 0) {
|
||||||
|
perror("read");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nbytes < sizeof(struct can_frame)) {
|
||||||
|
fprintf(stderr, "read: incomplete CAN frame\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
stat[i].recv_frames++;
|
||||||
|
stat[i].recv_bits_payload += frame.can_dlc*8;
|
||||||
|
stat[i].recv_bits_total += frame.can_dlc*8;
|
||||||
|
if (frame.can_id & CAN_EFF_FLAG)
|
||||||
|
stat[i].recv_bits_total += 67;
|
||||||
|
else
|
||||||
|
stat[i].recv_bits_total += 47;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
alarm(1);
|
|
||||||
|
|
||||||
if (redraw)
|
|
||||||
printf("%s", CLR_SCREEN);
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
|
|
||||||
FD_ZERO(&rdfs);
|
|
||||||
for (i=0; i<currmax; i++)
|
for (i=0; i<currmax; i++)
|
||||||
FD_SET(s[i], &rdfs);
|
close(s[i]);
|
||||||
|
|
||||||
savesigmask = sigmask;
|
return 0;
|
||||||
|
|
||||||
if (pselect(s[currmax-1]+1, &rdfs, NULL, NULL, NULL, &sigmask) < 0) {
|
|
||||||
//perror("pselect");
|
|
||||||
sigmask = savesigmask;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<currmax; i++) { /* check all CAN RAW sockets */
|
|
||||||
|
|
||||||
if (FD_ISSET(s[i], &rdfs)) {
|
|
||||||
|
|
||||||
nbytes = read(s[i], &frame, sizeof(struct can_frame));
|
|
||||||
|
|
||||||
if (nbytes < 0) {
|
|
||||||
perror("read");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nbytes < sizeof(struct can_frame)) {
|
|
||||||
fprintf(stderr, "read: incomplete CAN frame\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
stat[i].recv_frames++;
|
|
||||||
stat[i].recv_bits_payload += frame.can_dlc*8;
|
|
||||||
stat[i].recv_bits_total += frame.can_dlc*8;
|
|
||||||
if (frame.can_id & CAN_EFF_FLAG)
|
|
||||||
stat[i].recv_bits_total += 67;
|
|
||||||
else
|
|
||||||
stat[i].recv_bits_total += 47;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<currmax; i++)
|
|
||||||
close(s[i]);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
762
candump.c
762
candump.c
|
|
@ -98,476 +98,476 @@ static volatile int running = 1;
|
||||||
|
|
||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
|
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
|
||||||
fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg);
|
fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg);
|
||||||
fprintf(stderr, "Options: -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n");
|
fprintf(stderr, "Options: -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n");
|
||||||
fprintf(stderr, " -c (increment color mode level)\n");
|
fprintf(stderr, " -c (increment color mode level)\n");
|
||||||
fprintf(stderr, " -i (binary output - may exceed 80 chars/line)\n");
|
fprintf(stderr, " -i (binary output - may exceed 80 chars/line)\n");
|
||||||
fprintf(stderr, " -a (enable additional ASCII output)\n");
|
fprintf(stderr, " -a (enable additional ASCII output)\n");
|
||||||
fprintf(stderr, " -s <level> (silent mode - 1: animation 2: completely silent)\n");
|
fprintf(stderr, " -s <level> (silent mode - 1: animation 2: completely silent)\n");
|
||||||
fprintf(stderr, " -b <can> (bridge mode - send received frames to <can>)\n");
|
fprintf(stderr, " -b <can> (bridge mode - send received frames to <can>)\n");
|
||||||
fprintf(stderr, " -B <can> (bridge mode - like '-b' with disabled loopback)\n");
|
fprintf(stderr, " -B <can> (bridge mode - like '-b' with disabled loopback)\n");
|
||||||
fprintf(stderr, " -l (log CAN-frames into file)\n");
|
fprintf(stderr, " -l (log CAN-frames into file)\n");
|
||||||
fprintf(stderr, " -L (use log file format on stdout)\n");
|
fprintf(stderr, " -L (use log file format on stdout)\n");
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "Up to %d CAN interfaces with optional filter sets can be specified\n", MAXSOCK);
|
fprintf(stderr, "Up to %d CAN interfaces with optional filter sets can be specified\n", MAXSOCK);
|
||||||
fprintf(stderr, "on the commandline in the form: <ifname>[,filter]*\n");
|
fprintf(stderr, "on the commandline in the form: <ifname>[,filter]*\n");
|
||||||
fprintf(stderr, "\nUp to %d comma separated filters can be specified for each given CAN interface:\n", MAXFILTER);
|
fprintf(stderr, "\nUp to %d comma separated filters can be specified for each given CAN interface:\n", MAXFILTER);
|
||||||
fprintf(stderr, " <can_id>:<can_mask> (matches when <received_can_id> & mask == can_id & mask)\n");
|
fprintf(stderr, " <can_id>:<can_mask> (matches when <received_can_id> & mask == can_id & mask)\n");
|
||||||
fprintf(stderr, " <can_id>~<can_mask> (matches when <received_can_id> & mask != can_id & mask)\n");
|
fprintf(stderr, " <can_id>~<can_mask> (matches when <received_can_id> & mask != can_id & mask)\n");
|
||||||
fprintf(stderr, " #<error_mask> (set error frame filter, see include/linux/can/error.h)\n");
|
fprintf(stderr, " #<error_mask> (set error frame filter, see include/linux/can/error.h)\n");
|
||||||
fprintf(stderr, "\nUse interface name '%s' to receive from all CAN interfaces.\n", ANYDEV);
|
fprintf(stderr, "\nUse interface name '%s' to receive from all CAN interfaces.\n", ANYDEV);
|
||||||
fprintf(stderr, "CAN IDs, masks and data content are given and expected in hexadecimal values.\n");
|
fprintf(stderr, "CAN IDs, masks and data content are given and expected in hexadecimal values.\n");
|
||||||
fprintf(stderr, "\nExamples:\n");
|
fprintf(stderr, "\nExamples:\n");
|
||||||
fprintf(stderr, "%s -c -c -ta can0,123:7FF,400:700,#000000FF can2,400~7F0 can3 can8\n", prg);
|
fprintf(stderr, "%s -c -c -ta can0,123:7FF,400:700,#000000FF can2,400~7F0 can3 can8\n", prg);
|
||||||
fprintf(stderr, "%s -l any,0~0,#FFFFFFFF (log only error frames but no(!) data frames)\n", prg);
|
fprintf(stderr, "%s -l any,0~0,#FFFFFFFF (log only error frames but no(!) data frames)\n", prg);
|
||||||
fprintf(stderr, "%s vcan2,92345678:9FFFFFFF (match only for extended CAN ID 12345678)\n", prg);
|
fprintf(stderr, "%s vcan2,92345678:9FFFFFFF (match only for extended CAN ID 12345678)\n", prg);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void sigterm(int signo)
|
void sigterm(int signo)
|
||||||
{
|
{
|
||||||
running = 0;
|
running = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int idx2dindex(int ifidx, int socket) {
|
int idx2dindex(int ifidx, int socket) {
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
|
|
||||||
for (i=0; i < MAXIFNAMES; i++) {
|
for (i=0; i < MAXIFNAMES; i++) {
|
||||||
if (dindex[i] == ifidx)
|
if (dindex[i] == ifidx)
|
||||||
return i;
|
return i;
|
||||||
}
|
|
||||||
|
|
||||||
/* create new interface index cache entry */
|
|
||||||
|
|
||||||
/* remove index cache zombies first */
|
|
||||||
for (i=0; i < MAXIFNAMES; i++) {
|
|
||||||
if (dindex[i]) {
|
|
||||||
ifr.ifr_ifindex = dindex[i];
|
|
||||||
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
|
|
||||||
dindex[i] = 0;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i < MAXIFNAMES; i++)
|
/* create new interface index cache entry */
|
||||||
if (!dindex[i]) /* free entry */
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (i == MAXIFNAMES) {
|
/* remove index cache zombies first */
|
||||||
printf("Interface index cache only supports %d interfaces.\n",
|
for (i=0; i < MAXIFNAMES; i++) {
|
||||||
MAXIFNAMES);
|
if (dindex[i]) {
|
||||||
exit(1);
|
ifr.ifr_ifindex = dindex[i];
|
||||||
}
|
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
|
||||||
|
dindex[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dindex[i] = ifidx;
|
for (i=0; i < MAXIFNAMES; i++)
|
||||||
|
if (!dindex[i]) /* free entry */
|
||||||
|
break;
|
||||||
|
|
||||||
ifr.ifr_ifindex = ifidx;
|
if (i == MAXIFNAMES) {
|
||||||
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
|
printf("Interface index cache only supports %d interfaces.\n",
|
||||||
perror("SIOCGIFNAME");
|
MAXIFNAMES);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if (max_devname_len < strlen(ifr.ifr_name))
|
dindex[i] = ifidx;
|
||||||
max_devname_len = strlen(ifr.ifr_name);
|
|
||||||
|
|
||||||
strcpy(devname[i], ifr.ifr_name);
|
ifr.ifr_ifindex = ifidx;
|
||||||
|
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
|
||||||
|
perror("SIOCGIFNAME");
|
||||||
|
|
||||||
|
if (max_devname_len < strlen(ifr.ifr_name))
|
||||||
|
max_devname_len = strlen(ifr.ifr_name);
|
||||||
|
|
||||||
|
strcpy(devname[i], ifr.ifr_name);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("new index %d (%s)\n", i, devname[i]);
|
printf("new index %d (%s)\n", i, devname[i]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
fd_set rdfs;
|
fd_set rdfs;
|
||||||
int s[MAXSOCK];
|
int s[MAXSOCK];
|
||||||
int bridge = 0;
|
int bridge = 0;
|
||||||
unsigned char timestamp = 0;
|
unsigned char timestamp = 0;
|
||||||
unsigned char silent = 0;
|
unsigned char silent = 0;
|
||||||
unsigned char silentani = 0;
|
unsigned char silentani = 0;
|
||||||
unsigned char color = 0;
|
unsigned char color = 0;
|
||||||
unsigned char view = 0;
|
unsigned char view = 0;
|
||||||
unsigned char log = 0;
|
unsigned char log = 0;
|
||||||
unsigned char logfrmt = 0;
|
unsigned char logfrmt = 0;
|
||||||
int opt, ret;
|
int opt, ret;
|
||||||
int currmax, numfilter;
|
int currmax, numfilter;
|
||||||
char *ptr, *nptr;
|
char *ptr, *nptr;
|
||||||
struct sockaddr_can addr;
|
struct sockaddr_can addr;
|
||||||
struct can_filter rfilter[MAXFILTER];
|
struct can_filter rfilter[MAXFILTER];
|
||||||
can_err_mask_t err_mask;
|
can_err_mask_t err_mask;
|
||||||
struct can_frame frame;
|
struct can_frame frame;
|
||||||
int nbytes, i;
|
int nbytes, i;
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
struct timeval tv, last_tv;
|
struct timeval tv, last_tv;
|
||||||
FILE *logfile = NULL;
|
FILE *logfile = NULL;
|
||||||
|
|
||||||
signal(SIGTERM, sigterm);
|
signal(SIGTERM, sigterm);
|
||||||
signal(SIGHUP, sigterm);
|
signal(SIGHUP, sigterm);
|
||||||
signal(SIGINT, sigterm);
|
signal(SIGINT, sigterm);
|
||||||
|
|
||||||
last_tv.tv_sec = 0;
|
last_tv.tv_sec = 0;
|
||||||
last_tv.tv_usec = 0;
|
last_tv.tv_usec = 0;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "t:cias:b:B:lLh?")) != -1) {
|
while ((opt = getopt(argc, argv, "t:cias:b:B:lLh?")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 't':
|
case 't':
|
||||||
timestamp = optarg[0];
|
timestamp = optarg[0];
|
||||||
if ((timestamp != 'a') && (timestamp != 'A') &&
|
if ((timestamp != 'a') && (timestamp != 'A') &&
|
||||||
(timestamp != 'd') && (timestamp != 'z')) {
|
(timestamp != 'd') && (timestamp != 'z')) {
|
||||||
printf("%s: unknown timestamp mode '%c' - ignored\n",
|
printf("%s: unknown timestamp mode '%c' - ignored\n",
|
||||||
basename(argv[0]), optarg[0]);
|
basename(argv[0]), optarg[0]);
|
||||||
timestamp = 0;
|
timestamp = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
color++;
|
color++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
view |= CANLIB_VIEW_BINARY;
|
view |= CANLIB_VIEW_BINARY;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'a':
|
case 'a':
|
||||||
view |= CANLIB_VIEW_ASCII;
|
view |= CANLIB_VIEW_ASCII;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
silent = atoi(optarg);
|
silent = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'b':
|
case 'b':
|
||||||
case 'B':
|
case 'B':
|
||||||
if (strlen(optarg) >= IFNAMSIZ) {
|
if (strlen(optarg) >= IFNAMSIZ) {
|
||||||
printf("Name of CAN device '%s' is too long!\n\n", optarg);
|
printf("Name of CAN device '%s' is too long!\n\n", optarg);
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
bridge = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
bridge = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
||||||
if (bridge < 0) {
|
if (bridge < 0) {
|
||||||
perror("bridge socket");
|
perror("bridge socket");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
addr.can_family = AF_CAN;
|
addr.can_family = AF_CAN;
|
||||||
strcpy(ifr.ifr_name, optarg);
|
strcpy(ifr.ifr_name, optarg);
|
||||||
if (ioctl(bridge, SIOCGIFINDEX, &ifr) < 0)
|
if (ioctl(bridge, SIOCGIFINDEX, &ifr) < 0)
|
||||||
perror("SIOCGIFINDEX");
|
perror("SIOCGIFINDEX");
|
||||||
addr.can_ifindex = ifr.ifr_ifindex;
|
addr.can_ifindex = ifr.ifr_ifindex;
|
||||||
|
|
||||||
if (!addr.can_ifindex) {
|
if (!addr.can_ifindex) {
|
||||||
perror("invalid bridge interface");
|
perror("invalid bridge interface");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt == 'B') {
|
if (opt == 'B') {
|
||||||
int loopback = 0;
|
int loopback = 0;
|
||||||
|
|
||||||
setsockopt(bridge, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
|
setsockopt(bridge, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
|
||||||
&loopback, sizeof(loopback));
|
&loopback, sizeof(loopback));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bind(bridge, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
if (bind(bridge, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||||
perror("bridge bind");
|
perror("bridge bind");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
log = 1;
|
log = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'L':
|
case 'L':
|
||||||
logfrmt = 1;
|
logfrmt = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
exit(1);
|
exit(1);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (optind == argc) {
|
if (optind == argc) {
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
currmax = argc - optind; /* find real number of CAN devices */
|
currmax = argc - optind; /* find real number of CAN devices */
|
||||||
|
|
||||||
if (currmax > MAXSOCK) {
|
if (currmax > MAXSOCK) {
|
||||||
printf("More than %d CAN devices given on commandline!\n", MAXSOCK);
|
printf("More than %d CAN devices given on commandline!\n", MAXSOCK);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i < currmax; i++) {
|
for (i=0; i < currmax; i++) {
|
||||||
|
|
||||||
ptr = argv[optind+i];
|
ptr = argv[optind+i];
|
||||||
nptr = strchr(ptr, ',');
|
nptr = strchr(ptr, ',');
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("open %d '%s'.\n", i, ptr);
|
printf("open %d '%s'.\n", i, ptr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
||||||
if (s[i] < 0) {
|
if (s[i] < 0) {
|
||||||
perror("socket");
|
perror("socket");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nptr)
|
if (nptr)
|
||||||
nbytes = nptr - ptr; /* interface name is up the first ',' */
|
nbytes = nptr - ptr; /* interface name is up the first ',' */
|
||||||
else
|
else
|
||||||
nbytes = strlen(ptr); /* no ',' found => no filter definitions */
|
nbytes = strlen(ptr); /* no ',' found => no filter definitions */
|
||||||
|
|
||||||
if (nbytes >= IFNAMSIZ) {
|
if (nbytes >= IFNAMSIZ) {
|
||||||
printf("name of CAN device '%s' is too long!\n", ptr);
|
printf("name of CAN device '%s' is too long!\n", ptr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbytes > max_devname_len)
|
if (nbytes > max_devname_len)
|
||||||
max_devname_len = nbytes; /* for nice printing */
|
max_devname_len = nbytes; /* for nice printing */
|
||||||
|
|
||||||
addr.can_family = AF_CAN;
|
addr.can_family = AF_CAN;
|
||||||
|
|
||||||
memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
|
memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
|
||||||
strncpy(ifr.ifr_name, ptr, nbytes);
|
strncpy(ifr.ifr_name, ptr, nbytes);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("using interface name '%s'.\n", ifr.ifr_name);
|
printf("using interface name '%s'.\n", ifr.ifr_name);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (strcmp(ANYDEV, ifr.ifr_name)) {
|
if (strcmp(ANYDEV, ifr.ifr_name)) {
|
||||||
if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
|
if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
|
||||||
perror("SIOCGIFINDEX");
|
perror("SIOCGIFINDEX");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
addr.can_ifindex = ifr.ifr_ifindex;
|
addr.can_ifindex = ifr.ifr_ifindex;
|
||||||
} else
|
} else
|
||||||
addr.can_ifindex = 0; /* any can interface */
|
addr.can_ifindex = 0; /* any can interface */
|
||||||
|
|
||||||
if (nptr) {
|
if (nptr) {
|
||||||
|
|
||||||
/* found a ',' after the interface name => check for filters */
|
/* found a ',' after the interface name => check for filters */
|
||||||
|
|
||||||
numfilter = 0;
|
numfilter = 0;
|
||||||
err_mask = 0;
|
err_mask = 0;
|
||||||
|
|
||||||
while (nptr) {
|
while (nptr) {
|
||||||
|
|
||||||
ptr = nptr+1; /* hop behind the ',' */
|
ptr = nptr+1; /* hop behind the ',' */
|
||||||
nptr = strchr(ptr, ','); /* update exit condition */
|
nptr = strchr(ptr, ','); /* update exit condition */
|
||||||
|
|
||||||
if (sscanf(ptr, "%lx:%lx",
|
if (sscanf(ptr, "%lx:%lx",
|
||||||
(long unsigned int *)
|
(long unsigned int *)
|
||||||
&rfilter[numfilter].can_id,
|
&rfilter[numfilter].can_id,
|
||||||
(long unsigned int *)
|
(long unsigned int *)
|
||||||
&rfilter[numfilter].can_mask) == 2) {
|
&rfilter[numfilter].can_mask) == 2) {
|
||||||
numfilter++;
|
numfilter++;
|
||||||
} else if (sscanf(ptr, "%lx~%lx",
|
} else if (sscanf(ptr, "%lx~%lx",
|
||||||
(long unsigned int *)
|
(long unsigned int *)
|
||||||
&rfilter[numfilter].can_id,
|
&rfilter[numfilter].can_id,
|
||||||
(long unsigned int *)
|
(long unsigned int *)
|
||||||
&rfilter[numfilter].can_mask) == 2) {
|
&rfilter[numfilter].can_mask) == 2) {
|
||||||
rfilter[numfilter].can_id |= CAN_INV_FILTER;
|
rfilter[numfilter].can_id |= CAN_INV_FILTER;
|
||||||
numfilter++;
|
numfilter++;
|
||||||
} else if (sscanf(ptr, "#%lx",
|
} else if (sscanf(ptr, "#%lx",
|
||||||
(long unsigned int *)&err_mask) != 1) {
|
(long unsigned int *)&err_mask) != 1) {
|
||||||
printf("Error in filter option parsing: '%s'\n", ptr);
|
printf("Error in filter option parsing: '%s'\n", ptr);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numfilter > MAXFILTER) {
|
if (numfilter > MAXFILTER) {
|
||||||
printf("Too many filters specified for '%s'.\n",
|
printf("Too many filters specified for '%s'.\n",
|
||||||
ifr.ifr_name);
|
ifr.ifr_name);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err_mask)
|
if (err_mask)
|
||||||
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_ERR_FILTER,
|
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_ERR_FILTER,
|
||||||
&err_mask, sizeof(err_mask));
|
&err_mask, sizeof(err_mask));
|
||||||
|
|
||||||
if (numfilter)
|
if (numfilter)
|
||||||
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FILTER,
|
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FILTER,
|
||||||
&rfilter, numfilter * sizeof(struct can_filter));
|
&rfilter, numfilter * sizeof(struct can_filter));
|
||||||
} /* if (nptr) */
|
} /* if (nptr) */
|
||||||
|
|
||||||
if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||||
perror("bind");
|
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);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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;
|
return 1;
|
||||||
} else if (nbytes < sizeof(struct can_frame)) {
|
|
||||||
fprintf(stderr,"bridge write: incomplete CAN frame\n");
|
|
||||||
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);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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 (timestamp || log || logfrmt)
|
||||||
if (ioctl(s[i], SIOCGSTAMP, &tv) < 0)
|
if (ioctl(s[i], SIOCGSTAMP, &tv) < 0)
|
||||||
perror("SIOCGSTAMP");
|
perror("SIOCGSTAMP");
|
||||||
|
|
||||||
|
|
||||||
idx = idx2dindex(addr.can_ifindex, s[i]);
|
idx = idx2dindex(addr.can_ifindex, s[i]);
|
||||||
|
|
||||||
if (log) {
|
if (log) {
|
||||||
/* log CAN frame with absolute timestamp & device */
|
/* log CAN frame with absolute timestamp & device */
|
||||||
fprintf(logfile, "(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
|
fprintf(logfile, "(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
|
||||||
fprintf(logfile, "%*s ", max_devname_len, devname[idx]);
|
fprintf(logfile, "%*s ", max_devname_len, devname[idx]);
|
||||||
/* without seperator as logfile use-case is parsing */
|
/* without seperator as logfile use-case is parsing */
|
||||||
fprint_canframe(logfile, &frame, "\n", 0);
|
fprint_canframe(logfile, &frame, "\n", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (logfrmt) {
|
if (logfrmt) {
|
||||||
/* print CAN frame in log file style to stdout */
|
/* print CAN frame in log file style to stdout */
|
||||||
printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
|
printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
|
||||||
printf("%*s ", max_devname_len, devname[idx]);
|
printf("%*s ", max_devname_len, devname[idx]);
|
||||||
fprint_canframe(stdout, &frame, "\n", 0);
|
fprint_canframe(stdout, &frame, "\n", 0);
|
||||||
goto out_fflush; /* no other output to stdout */
|
goto out_fflush; /* no other output to stdout */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (silent){
|
if (silent){
|
||||||
if (silent == 1) {
|
if (silent == 1) {
|
||||||
printf("%c\b", anichar[silentani%=MAXANI]);
|
printf("%c\b", anichar[silentani%=MAXANI]);
|
||||||
silentani++;
|
silentani++;
|
||||||
}
|
}
|
||||||
goto out_fflush; /* no other output to stdout */
|
goto out_fflush; /* no other output to stdout */
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" %s", (color>2)?col_on[idx%MAXCOL]:"");
|
printf(" %s", (color>2)?col_on[idx%MAXCOL]:"");
|
||||||
|
|
||||||
switch (timestamp) {
|
switch (timestamp) {
|
||||||
|
|
||||||
case 'a': /* absolute with timestamp */
|
case 'a': /* absolute with timestamp */
|
||||||
printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
|
printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'A': /* absolute with date */
|
case 'A': /* absolute with date */
|
||||||
{
|
{
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
char timestring[25];
|
char timestring[25];
|
||||||
|
|
||||||
tm = *localtime(&tv.tv_sec);
|
tm = *localtime(&tv.tv_sec);
|
||||||
strftime(timestring, 24, "%Y-%m-%d %H:%M:%S", &tm);
|
strftime(timestring, 24, "%Y-%m-%d %H:%M:%S", &tm);
|
||||||
printf("(%s.%06ld) ", timestring, tv.tv_usec);
|
printf("(%s.%06ld) ", timestring, tv.tv_usec);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd': /* delta */
|
case 'd': /* delta */
|
||||||
case 'z': /* starting with zero */
|
case 'z': /* starting with zero */
|
||||||
{
|
{
|
||||||
struct timeval diff;
|
struct timeval diff;
|
||||||
|
|
||||||
if (last_tv.tv_sec == 0) /* first init */
|
if (last_tv.tv_sec == 0) /* first init */
|
||||||
last_tv = tv;
|
last_tv = tv;
|
||||||
diff.tv_sec = tv.tv_sec - last_tv.tv_sec;
|
diff.tv_sec = tv.tv_sec - last_tv.tv_sec;
|
||||||
diff.tv_usec = tv.tv_usec - last_tv.tv_usec;
|
diff.tv_usec = tv.tv_usec - last_tv.tv_usec;
|
||||||
if (diff.tv_usec < 0)
|
if (diff.tv_usec < 0)
|
||||||
diff.tv_sec--, diff.tv_usec += 1000000;
|
diff.tv_sec--, diff.tv_usec += 1000000;
|
||||||
if (diff.tv_sec < 0)
|
if (diff.tv_sec < 0)
|
||||||
diff.tv_sec = diff.tv_usec = 0;
|
diff.tv_sec = diff.tv_usec = 0;
|
||||||
printf("(%ld.%06ld) ", diff.tv_sec, diff.tv_usec);
|
printf("(%ld.%06ld) ", diff.tv_sec, diff.tv_usec);
|
||||||
|
|
||||||
if (timestamp == 'd')
|
if (timestamp == 'd')
|
||||||
last_tv = tv; /* update for delta calculation */
|
last_tv = tv; /* update for delta calculation */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: /* no timestamp output */
|
default: /* no timestamp output */
|
||||||
break;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
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++)
|
for (i=0; i<currmax; i++)
|
||||||
close(s[i]);
|
close(s[i]);
|
||||||
|
|
||||||
if (bridge)
|
if (bridge)
|
||||||
close(bridge);
|
close(bridge);
|
||||||
|
|
||||||
if (log)
|
if (log)
|
||||||
fclose(logfile);
|
fclose(logfile);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
514
cangen.c
514
cangen.c
|
|
@ -80,306 +80,306 @@ static unsigned long long enobufs_count;
|
||||||
|
|
||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "\n%s: generate CAN frames\n\n", prg);
|
fprintf(stderr, "\n%s: generate CAN frames\n\n", prg);
|
||||||
fprintf(stderr, "Usage: %s [options] <CAN interface>\n", prg);
|
fprintf(stderr, "Usage: %s [options] <CAN interface>\n", prg);
|
||||||
fprintf(stderr, "Options: -g <ms> (gap in milli seconds "
|
fprintf(stderr, "Options: -g <ms> (gap in milli seconds "
|
||||||
"- default: %d ms)\n", DEFAULT_GAP);
|
"- default: %d ms)\n", DEFAULT_GAP);
|
||||||
fprintf(stderr, " -e (generate extended frame mode "
|
fprintf(stderr, " -e (generate extended frame mode "
|
||||||
"(EFF) CAN frames)\n");
|
"(EFF) CAN frames)\n");
|
||||||
fprintf(stderr, " -I <mode> (CAN ID"
|
fprintf(stderr, " -I <mode> (CAN ID"
|
||||||
" generation mode - see below)\n");
|
" generation mode - see below)\n");
|
||||||
fprintf(stderr, " -L <mode> (CAN data length code (dlc)"
|
fprintf(stderr, " -L <mode> (CAN data length code (dlc)"
|
||||||
" generation mode - see below)\n");
|
" generation mode - see below)\n");
|
||||||
fprintf(stderr, " -D <mode> (CAN data (payload)"
|
fprintf(stderr, " -D <mode> (CAN data (payload)"
|
||||||
" generation mode - see below)\n");
|
" generation mode - see below)\n");
|
||||||
fprintf(stderr, " -i (ignore -ENOBUFS return values on"
|
fprintf(stderr, " -i (ignore -ENOBUFS return values on"
|
||||||
" write() syscalls)\n");
|
" write() syscalls)\n");
|
||||||
fprintf(stderr, " -x (disable local loopback of "
|
fprintf(stderr, " -x (disable local loopback of "
|
||||||
"generated CAN frames)\n");
|
"generated CAN frames)\n");
|
||||||
fprintf(stderr, " -v (increment verbose level for "
|
fprintf(stderr, " -v (increment verbose level for "
|
||||||
"printing sent CAN frames)\n\n");
|
"printing sent CAN frames)\n\n");
|
||||||
fprintf(stderr, "Generation modes:\n");
|
fprintf(stderr, "Generation modes:\n");
|
||||||
fprintf(stderr, "'r' => random values (default)\n");
|
fprintf(stderr, "'r' => random values (default)\n");
|
||||||
fprintf(stderr, "'i' => increment values\n");
|
fprintf(stderr, "'i' => increment values\n");
|
||||||
fprintf(stderr, "<hexvalue> => fix value using <hexvalue>\n\n");
|
fprintf(stderr, "<hexvalue> => fix value using <hexvalue>\n\n");
|
||||||
fprintf(stderr, "When incrementing the CAN data the data length code "
|
fprintf(stderr, "When incrementing the CAN data the data length code "
|
||||||
"minimum is set to 1.\n");
|
"minimum is set to 1.\n");
|
||||||
fprintf(stderr, "CAN IDs and data content are given and expected in hexadecimal values.\n\n");
|
fprintf(stderr, "CAN IDs and data content are given and expected in hexadecimal values.\n\n");
|
||||||
fprintf(stderr, "Examples:\n");
|
fprintf(stderr, "Examples:\n");
|
||||||
fprintf(stderr, "%s vcan0 -g 4 -I 42A -L 1 -D i -v -v ", prg);
|
fprintf(stderr, "%s vcan0 -g 4 -I 42A -L 1 -D i -v -v ", prg);
|
||||||
fprintf(stderr, "(fixed CAN ID and length, inc. data)\n");
|
fprintf(stderr, "(fixed CAN ID and length, inc. data)\n");
|
||||||
fprintf(stderr, "%s vcan0 -e -L i -v -v -v ", prg);
|
fprintf(stderr, "%s vcan0 -e -L i -v -v -v ", prg);
|
||||||
fprintf(stderr, "(generate EFF frames, incr. length)\n");
|
fprintf(stderr, "(generate EFF frames, incr. length)\n");
|
||||||
fprintf(stderr, "%s vcan0 -D 11223344DEADBEEF -L 8 ", prg);
|
fprintf(stderr, "%s vcan0 -D 11223344DEADBEEF -L 8 ", prg);
|
||||||
fprintf(stderr, "(fixed CAN data payload and length)\n");
|
fprintf(stderr, "(fixed CAN data payload and length)\n");
|
||||||
fprintf(stderr, "%s vcan0 -g 0 -i -x ", prg);
|
fprintf(stderr, "%s vcan0 -g 0 -i -x ", prg);
|
||||||
fprintf(stderr, "(full load test ignoring -ENOBUFS)\n");
|
fprintf(stderr, "(full load test ignoring -ENOBUFS)\n");
|
||||||
fprintf(stderr, "%s vcan0 ", prg);
|
fprintf(stderr, "%s vcan0 ", prg);
|
||||||
fprintf(stderr, "(my favourite default :)\n\n");
|
fprintf(stderr, "(my favourite default :)\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void sigterm(int signo)
|
void sigterm(int signo)
|
||||||
{
|
{
|
||||||
running = 0;
|
running = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
unsigned long gap = DEFAULT_GAP;
|
unsigned long gap = DEFAULT_GAP;
|
||||||
unsigned char ignore_enobufs = 0;
|
unsigned char ignore_enobufs = 0;
|
||||||
unsigned char extended = 0;
|
unsigned char extended = 0;
|
||||||
unsigned char id_mode = MODE_RANDOM;
|
unsigned char id_mode = MODE_RANDOM;
|
||||||
unsigned char data_mode = MODE_RANDOM;
|
unsigned char data_mode = MODE_RANDOM;
|
||||||
unsigned char dlc_mode = MODE_RANDOM;
|
unsigned char dlc_mode = MODE_RANDOM;
|
||||||
unsigned char loopback_disable = 0;
|
unsigned char loopback_disable = 0;
|
||||||
unsigned char verbose = 0;
|
unsigned char verbose = 0;
|
||||||
uint64_t incdata = 0;
|
uint64_t incdata = 0;
|
||||||
|
|
||||||
int opt;
|
int opt;
|
||||||
int s; /* socket */
|
int s; /* socket */
|
||||||
|
|
||||||
struct sockaddr_can addr;
|
struct sockaddr_can addr;
|
||||||
static struct can_frame frame;
|
static struct can_frame frame;
|
||||||
int nbytes;
|
int nbytes;
|
||||||
int i;
|
int i;
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
|
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
|
|
||||||
signal(SIGTERM, sigterm);
|
signal(SIGTERM, sigterm);
|
||||||
signal(SIGHUP, sigterm);
|
signal(SIGHUP, sigterm);
|
||||||
signal(SIGINT, sigterm);
|
signal(SIGINT, sigterm);
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "ig:eI:L:D:xvh?")) != -1) {
|
while ((opt = getopt(argc, argv, "ig:eI:L:D:xvh?")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
ignore_enobufs = 1;
|
ignore_enobufs = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'g':
|
case 'g':
|
||||||
gap = strtoul(optarg, NULL, 10);
|
gap = strtoul(optarg, NULL, 10);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'e':
|
case 'e':
|
||||||
extended = 1;
|
extended = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'I':
|
case 'I':
|
||||||
if (optarg[0] == 'r') {
|
if (optarg[0] == 'r') {
|
||||||
id_mode = MODE_RANDOM;
|
id_mode = MODE_RANDOM;
|
||||||
} else if (optarg[0] == 'i') {
|
} else if (optarg[0] == 'i') {
|
||||||
id_mode = MODE_INCREMENT;
|
id_mode = MODE_INCREMENT;
|
||||||
} else {
|
} else {
|
||||||
id_mode = MODE_FIX;
|
id_mode = MODE_FIX;
|
||||||
frame.can_id = strtoul(optarg, NULL, 16);
|
frame.can_id = strtoul(optarg, NULL, 16);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'L':
|
case 'L':
|
||||||
if (optarg[0] == 'r') {
|
if (optarg[0] == 'r') {
|
||||||
dlc_mode = MODE_RANDOM;
|
dlc_mode = MODE_RANDOM;
|
||||||
} else if (optarg[0] == 'i') {
|
} else if (optarg[0] == 'i') {
|
||||||
dlc_mode = MODE_INCREMENT;
|
dlc_mode = MODE_INCREMENT;
|
||||||
} else {
|
} else {
|
||||||
dlc_mode = MODE_FIX;
|
dlc_mode = MODE_FIX;
|
||||||
frame.can_dlc = atoi(optarg)%9;
|
frame.can_dlc = atoi(optarg)%9;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'D':
|
case 'D':
|
||||||
if (optarg[0] == 'r') {
|
if (optarg[0] == 'r') {
|
||||||
data_mode = MODE_RANDOM;
|
data_mode = MODE_RANDOM;
|
||||||
} else if (optarg[0] == 'i') {
|
} else if (optarg[0] == 'i') {
|
||||||
data_mode = MODE_INCREMENT;
|
data_mode = MODE_INCREMENT;
|
||||||
} else {
|
} else {
|
||||||
data_mode = MODE_FIX;
|
data_mode = MODE_FIX;
|
||||||
incdata = strtoull(optarg, NULL, 16);
|
incdata = strtoull(optarg, NULL, 16);
|
||||||
for (i=0; i<8 ;i++)
|
for (i=0; i<8 ;i++)
|
||||||
frame.data[i] = (incdata >> (7-i)*8) & 0xFFULL;
|
frame.data[i] = (incdata >> (7-i)*8) & 0xFFULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'v':
|
case 'v':
|
||||||
verbose++;
|
verbose++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'x':
|
case 'x':
|
||||||
loopback_disable = 1;
|
loopback_disable = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '?':
|
case '?':
|
||||||
case 'h':
|
case 'h':
|
||||||
default:
|
default:
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (optind == argc) {
|
if (optind == argc) {
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ts.tv_sec = gap / 1000;
|
ts.tv_sec = gap / 1000;
|
||||||
ts.tv_nsec = (gap % 1000) * 1000000;
|
ts.tv_nsec = (gap % 1000) * 1000000;
|
||||||
|
|
||||||
|
|
||||||
if (id_mode == MODE_FIX) {
|
if (id_mode == MODE_FIX) {
|
||||||
|
|
||||||
/* recognize obviously missing commandline option */
|
/* recognize obviously missing commandline option */
|
||||||
if ((frame.can_id > 0x7FF) && !extended) {
|
if ((frame.can_id > 0x7FF) && !extended) {
|
||||||
printf("The given CAN-ID is greater than 0x7FF and "
|
printf("The given CAN-ID is greater than 0x7FF and "
|
||||||
"the '-e' option is not set.\n");
|
"the '-e' option is not set.\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extended)
|
||||||
|
frame.can_id &= CAN_EFF_MASK;
|
||||||
|
else
|
||||||
|
frame.can_id &= CAN_SFF_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extended)
|
if (extended)
|
||||||
frame.can_id &= CAN_EFF_MASK;
|
frame.can_id |= CAN_EFF_FLAG;
|
||||||
else
|
|
||||||
frame.can_id &= CAN_SFF_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (extended)
|
if ((data_mode == MODE_INCREMENT) && !frame.can_dlc)
|
||||||
frame.can_id |= CAN_EFF_FLAG;
|
|
||||||
|
|
||||||
if ((data_mode == MODE_INCREMENT) && !frame.can_dlc)
|
|
||||||
frame.can_dlc = 1; /* min dlc value for incr. data */
|
|
||||||
|
|
||||||
if (strlen(argv[optind]) >= IFNAMSIZ) {
|
|
||||||
printf("Name of CAN device '%s' is too long!\n\n", argv[optind]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
|
|
||||||
perror("socket");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr.can_family = AF_CAN;
|
|
||||||
|
|
||||||
strcpy(ifr.ifr_name, argv[optind]);
|
|
||||||
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
|
|
||||||
perror("SIOCGIFINDEX");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
addr.can_ifindex = ifr.ifr_ifindex;
|
|
||||||
|
|
||||||
/* disable default receive filter on this RAW socket */
|
|
||||||
/* This is obsolete as we do not read from the socket at all, but for */
|
|
||||||
/* this reason we can remove the receive list in the Kernel to save a */
|
|
||||||
/* little (really a very little!) CPU usage. */
|
|
||||||
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
|
|
||||||
|
|
||||||
if (loopback_disable) {
|
|
||||||
int loopback = 0;
|
|
||||||
|
|
||||||
setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
|
|
||||||
&loopback, sizeof(loopback));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
||||||
perror("bind");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (running) {
|
|
||||||
|
|
||||||
if (id_mode == MODE_RANDOM) {
|
|
||||||
|
|
||||||
frame.can_id = random();
|
|
||||||
|
|
||||||
if (extended) {
|
|
||||||
frame.can_id &= CAN_EFF_MASK;
|
|
||||||
frame.can_id |= CAN_EFF_FLAG;
|
|
||||||
} else
|
|
||||||
frame.can_id &= CAN_SFF_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dlc_mode == MODE_RANDOM) {
|
|
||||||
|
|
||||||
frame.can_dlc = random() & 0xF;
|
|
||||||
|
|
||||||
if (frame.can_dlc & 8)
|
|
||||||
frame.can_dlc = 8; /* for about 50% of the frames */
|
|
||||||
|
|
||||||
if ((data_mode == MODE_INCREMENT) && !frame.can_dlc)
|
|
||||||
frame.can_dlc = 1; /* min dlc value for incr. data */
|
frame.can_dlc = 1; /* min dlc value for incr. data */
|
||||||
}
|
|
||||||
|
|
||||||
if (data_mode == MODE_RANDOM) {
|
if (strlen(argv[optind]) >= IFNAMSIZ) {
|
||||||
|
printf("Name of CAN device '%s' is too long!\n\n", argv[optind]);
|
||||||
/* that's what the 64 bit alignment of data[] is for ... :) */
|
|
||||||
*(unsigned long*)(&frame.data[0]) = random();
|
|
||||||
*(unsigned long*)(&frame.data[4]) = random();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (verbose) {
|
|
||||||
|
|
||||||
printf(" %s ", argv[optind]);
|
|
||||||
|
|
||||||
if (verbose > 1)
|
|
||||||
fprint_long_canframe(stdout, &frame, "\n", (verbose > 2)?1:0);
|
|
||||||
else
|
|
||||||
fprint_canframe(stdout, &frame, "\n", 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
nbytes = write(s, &frame, sizeof(struct can_frame));
|
|
||||||
if (nbytes < 0) {
|
|
||||||
if (errno != ENOBUFS) {
|
|
||||||
perror("write");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
if (!ignore_enobufs) {
|
|
||||||
perror("write");
|
|
||||||
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 ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
|
||||||
if (nanosleep(&ts, NULL))
|
perror("socket");
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr.can_family = AF_CAN;
|
||||||
|
|
||||||
|
strcpy(ifr.ifr_name, argv[optind]);
|
||||||
|
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
|
||||||
|
perror("SIOCGIFINDEX");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
addr.can_ifindex = ifr.ifr_ifindex;
|
||||||
|
|
||||||
|
/* disable default receive filter on this RAW socket */
|
||||||
|
/* This is obsolete as we do not read from the socket at all, but for */
|
||||||
|
/* this reason we can remove the receive list in the Kernel to save a */
|
||||||
|
/* little (really a very little!) CPU usage. */
|
||||||
|
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
|
||||||
|
|
||||||
|
if (loopback_disable) {
|
||||||
|
int loopback = 0;
|
||||||
|
|
||||||
|
setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
|
||||||
|
&loopback, sizeof(loopback));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||||
|
perror("bind");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (running) {
|
||||||
|
|
||||||
|
if (id_mode == MODE_RANDOM) {
|
||||||
|
|
||||||
|
frame.can_id = random();
|
||||||
|
|
||||||
|
if (extended) {
|
||||||
|
frame.can_id &= CAN_EFF_MASK;
|
||||||
|
frame.can_id |= CAN_EFF_FLAG;
|
||||||
|
} else
|
||||||
|
frame.can_id &= CAN_SFF_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dlc_mode == MODE_RANDOM) {
|
||||||
|
|
||||||
|
frame.can_dlc = random() & 0xF;
|
||||||
|
|
||||||
|
if (frame.can_dlc & 8)
|
||||||
|
frame.can_dlc = 8; /* for about 50% of the frames */
|
||||||
|
|
||||||
|
if ((data_mode == MODE_INCREMENT) && !frame.can_dlc)
|
||||||
|
frame.can_dlc = 1; /* min dlc value for incr. data */
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
if (id_mode == MODE_INCREMENT) {
|
||||||
|
|
||||||
frame.can_id++;
|
frame.can_id++;
|
||||||
|
|
||||||
if (extended) {
|
if (extended) {
|
||||||
frame.can_id &= CAN_EFF_MASK;
|
frame.can_id &= CAN_EFF_MASK;
|
||||||
frame.can_id |= CAN_EFF_FLAG;
|
frame.can_id |= CAN_EFF_FLAG;
|
||||||
} else
|
} else
|
||||||
frame.can_id &= CAN_SFF_MASK;
|
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 (dlc_mode == MODE_INCREMENT) {
|
if (enobufs_count)
|
||||||
|
printf("\nCounted %llu ENOBUFS return values on write().\n\n",
|
||||||
|
enobufs_count);
|
||||||
|
|
||||||
frame.can_dlc++;
|
close(s);
|
||||||
frame.can_dlc %= 9;
|
|
||||||
|
|
||||||
if ((data_mode == MODE_INCREMENT) && !frame.can_dlc)
|
return 0;
|
||||||
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);
|
|
||||||
|
|
||||||
close(s);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
558
canlogserver.c
558
canlogserver.c
|
|
@ -86,68 +86,68 @@ static volatile int running = 1;
|
||||||
|
|
||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
|
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
|
||||||
fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg);
|
fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg);
|
||||||
fprintf(stderr, "Options: -m <mask> (ID filter mask. Default 0x00000000) *\n");
|
fprintf(stderr, "Options: -m <mask> (ID filter mask. Default 0x00000000) *\n");
|
||||||
fprintf(stderr, " -v <value> (ID filter value. Default 0x00000000) *\n");
|
fprintf(stderr, " -v <value> (ID filter value. Default 0x00000000) *\n");
|
||||||
fprintf(stderr, " -i <0|1> (invert the specified ID filter) *\n");
|
fprintf(stderr, " -i <0|1> (invert the specified ID filter) *\n");
|
||||||
fprintf(stderr, " -e <emask> (mask for error frames)\n");
|
fprintf(stderr, " -e <emask> (mask for error frames)\n");
|
||||||
fprintf(stderr, " -p <port> (listen on port <port>. Default: %d)\n", DEFPORT);
|
fprintf(stderr, " -p <port> (listen on port <port>. Default: %d)\n", DEFPORT);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "* The CAN ID filter matches, when ...\n");
|
fprintf(stderr, "* The CAN ID filter matches, when ...\n");
|
||||||
fprintf(stderr, " <received_can_id> & mask == value & mask\n");
|
fprintf(stderr, " <received_can_id> & mask == value & mask\n");
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "When using more than one CAN interface the options\n");
|
fprintf(stderr, "When using more than one CAN interface the options\n");
|
||||||
fprintf(stderr, "m/v/i/e have comma seperated values e.g. '-m 0,7FF,0'\n");
|
fprintf(stderr, "m/v/i/e have comma seperated values e.g. '-m 0,7FF,0'\n");
|
||||||
fprintf(stderr, "\nUse interface name '%s' to receive from all CAN interfaces.\n\n", ANYDEV);
|
fprintf(stderr, "\nUse interface name '%s' to receive from all CAN interfaces.\n\n", ANYDEV);
|
||||||
}
|
}
|
||||||
|
|
||||||
int idx2dindex(int ifidx, int socket)
|
int idx2dindex(int ifidx, int socket)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
|
|
||||||
for (i=0; i<MAXDEV; i++) {
|
for (i=0; i<MAXDEV; i++) {
|
||||||
if (dindex[i] == ifidx)
|
if (dindex[i] == ifidx)
|
||||||
return i;
|
return i;
|
||||||
}
|
|
||||||
|
|
||||||
/* create new interface index cache entry */
|
|
||||||
|
|
||||||
/* remove index cache zombies first */
|
|
||||||
for (i=0; i < MAXDEV; i++) {
|
|
||||||
if (dindex[i]) {
|
|
||||||
ifr.ifr_ifindex = dindex[i];
|
|
||||||
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
|
|
||||||
dindex[i] = 0;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i < MAXDEV; i++)
|
/* create new interface index cache entry */
|
||||||
if (!dindex[i]) /* free entry */
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (i == MAXDEV) {
|
/* remove index cache zombies first */
|
||||||
printf("Interface index cache only supports %d interfaces.\n", MAXDEV);
|
for (i=0; i < MAXDEV; i++) {
|
||||||
exit(1);
|
if (dindex[i]) {
|
||||||
}
|
ifr.ifr_ifindex = dindex[i];
|
||||||
|
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
|
||||||
|
dindex[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dindex[i] = ifidx;
|
for (i=0; i < MAXDEV; i++)
|
||||||
|
if (!dindex[i]) /* free entry */
|
||||||
|
break;
|
||||||
|
|
||||||
ifr.ifr_ifindex = ifidx;
|
if (i == MAXDEV) {
|
||||||
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
|
printf("Interface index cache only supports %d interfaces.\n", MAXDEV);
|
||||||
perror("SIOCGIFNAME");
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if (max_devname_len < strlen(ifr.ifr_name))
|
dindex[i] = ifidx;
|
||||||
max_devname_len = strlen(ifr.ifr_name);
|
|
||||||
|
|
||||||
strcpy(devname[i], ifr.ifr_name);
|
ifr.ifr_ifindex = ifidx;
|
||||||
|
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
|
||||||
|
perror("SIOCGIFNAME");
|
||||||
|
|
||||||
|
if (max_devname_len < strlen(ifr.ifr_name))
|
||||||
|
max_devname_len = strlen(ifr.ifr_name);
|
||||||
|
|
||||||
|
strcpy(devname[i], ifr.ifr_name);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("new index %d (%s)\n", i, devname[i]);
|
printf("new index %d (%s)\n", i, devname[i]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -156,7 +156,7 @@ int idx2dindex(int ifidx, int socket)
|
||||||
*/
|
*/
|
||||||
void childdied(int i)
|
void childdied(int i)
|
||||||
{
|
{
|
||||||
wait(NULL);
|
wait(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -164,273 +164,273 @@ void childdied(int i)
|
||||||
*/
|
*/
|
||||||
void shutdown_gra(int i)
|
void shutdown_gra(int i)
|
||||||
{
|
{
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct sigaction signalaction;
|
struct sigaction signalaction;
|
||||||
sigset_t sigset;
|
sigset_t sigset;
|
||||||
fd_set rdfs;
|
fd_set rdfs;
|
||||||
int s[MAXDEV];
|
int s[MAXDEV];
|
||||||
int socki, accsocket;
|
int socki, accsocket;
|
||||||
canid_t mask[MAXDEV] = {0};
|
canid_t mask[MAXDEV] = {0};
|
||||||
canid_t value[MAXDEV] = {0};
|
canid_t value[MAXDEV] = {0};
|
||||||
int inv_filter[MAXDEV] = {0};
|
int inv_filter[MAXDEV] = {0};
|
||||||
can_err_mask_t err_mask[MAXDEV] = {0};
|
can_err_mask_t err_mask[MAXDEV] = {0};
|
||||||
int opt, ret;
|
int opt, ret;
|
||||||
int currmax = 1; /* we assume at least one can bus ;-) */
|
int currmax = 1; /* we assume at least one can bus ;-) */
|
||||||
struct sockaddr_can addr;
|
struct sockaddr_can addr;
|
||||||
struct can_filter rfilter;
|
struct can_filter rfilter;
|
||||||
struct can_frame frame;
|
struct can_frame frame;
|
||||||
int nbytes, i, j;
|
int nbytes, i, j;
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
struct timeval tv, last_tv;
|
struct timeval tv, last_tv;
|
||||||
int port = DEFPORT;
|
int port = DEFPORT;
|
||||||
struct sockaddr_in inaddr;
|
struct sockaddr_in inaddr;
|
||||||
struct sockaddr_in clientaddr;
|
struct sockaddr_in clientaddr;
|
||||||
socklen_t sin_size = sizeof(clientaddr);
|
socklen_t sin_size = sizeof(clientaddr);
|
||||||
char temp[128];
|
char temp[128];
|
||||||
|
|
||||||
sigemptyset(&sigset);
|
sigemptyset(&sigset);
|
||||||
signalaction.sa_handler = &childdied;
|
signalaction.sa_handler = &childdied;
|
||||||
signalaction.sa_mask = sigset;
|
signalaction.sa_mask = sigset;
|
||||||
signalaction.sa_flags = 0;
|
signalaction.sa_flags = 0;
|
||||||
sigaction(SIGCHLD, &signalaction, NULL); /* install signal for dying child */
|
sigaction(SIGCHLD, &signalaction, NULL); /* install signal for dying child */
|
||||||
signalaction.sa_handler = &shutdown_gra;
|
signalaction.sa_handler = &shutdown_gra;
|
||||||
signalaction.sa_mask = sigset;
|
signalaction.sa_mask = sigset;
|
||||||
signalaction.sa_flags = 0;
|
signalaction.sa_flags = 0;
|
||||||
sigaction(SIGTERM, &signalaction, NULL); /* install Signal for termination */
|
sigaction(SIGTERM, &signalaction, NULL); /* install Signal for termination */
|
||||||
sigaction(SIGINT, &signalaction, NULL); /* install Signal for termination */
|
sigaction(SIGINT, &signalaction, NULL); /* install Signal for termination */
|
||||||
|
|
||||||
|
|
||||||
last_tv.tv_sec = 0;
|
last_tv.tv_sec = 0;
|
||||||
last_tv.tv_usec = 0;
|
last_tv.tv_usec = 0;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "m:v:i:e:p:?")) != -1) {
|
while ((opt = getopt(argc, argv, "m:v:i:e:p:?")) != -1) {
|
||||||
|
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'm':
|
case 'm':
|
||||||
i = sscanf(optarg, "%x,%x,%x,%x,%x,%x",
|
i = sscanf(optarg, "%x,%x,%x,%x,%x,%x",
|
||||||
&mask[0], &mask[1], &mask[2],
|
&mask[0], &mask[1], &mask[2],
|
||||||
&mask[3], &mask[4], &mask[5]);
|
&mask[3], &mask[4], &mask[5]);
|
||||||
if (i > currmax)
|
if (i > currmax)
|
||||||
currmax = i;
|
currmax = i;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'v':
|
case 'v':
|
||||||
i = sscanf(optarg, "%x,%x,%x,%x,%x,%x",
|
i = sscanf(optarg, "%x,%x,%x,%x,%x,%x",
|
||||||
&value[0], &value[1], &value[2],
|
&value[0], &value[1], &value[2],
|
||||||
&value[3], &value[4], &value[5]);
|
&value[3], &value[4], &value[5]);
|
||||||
if (i > currmax)
|
if (i > currmax)
|
||||||
currmax = i;
|
currmax = i;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
i = sscanf(optarg, "%d,%d,%d,%d,%d,%d",
|
i = sscanf(optarg, "%d,%d,%d,%d,%d,%d",
|
||||||
&inv_filter[0], &inv_filter[1], &inv_filter[2],
|
&inv_filter[0], &inv_filter[1], &inv_filter[2],
|
||||||
&inv_filter[3], &inv_filter[4], &inv_filter[5]);
|
&inv_filter[3], &inv_filter[4], &inv_filter[5]);
|
||||||
if (i > currmax)
|
if (i > currmax)
|
||||||
currmax = i;
|
currmax = i;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'e':
|
case 'e':
|
||||||
i = sscanf(optarg, "%x,%x,%x,%x,%x,%x",
|
i = sscanf(optarg, "%x,%x,%x,%x,%x,%x",
|
||||||
&err_mask[0], &err_mask[1], &err_mask[2],
|
&err_mask[0], &err_mask[1], &err_mask[2],
|
||||||
&err_mask[3], &err_mask[4], &err_mask[5]);
|
&err_mask[3], &err_mask[4], &err_mask[5]);
|
||||||
if (i > currmax)
|
if (i > currmax)
|
||||||
currmax = i;
|
currmax = i;
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
port = atoi(optarg);
|
port = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
exit(1);
|
exit(1);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (optind == argc) {
|
if (optind == argc) {
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
|
||||||
|
|
||||||
/* count in options higher than device count ? */
|
|
||||||
if (optind + currmax > argc) {
|
|
||||||
printf("low count of CAN devices!\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
currmax = argc - optind; /* find real number of CAN devices */
|
|
||||||
|
|
||||||
if (currmax > MAXDEV) {
|
|
||||||
printf("More than %d CAN devices!\n", MAXDEV);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
socki = socket(PF_INET, SOCK_STREAM, 0);
|
|
||||||
if (socki < 0) {
|
|
||||||
perror("socket");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
inaddr.sin_family = AF_INET;
|
|
||||||
inaddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
||||||
inaddr.sin_port = htons(port);
|
|
||||||
|
|
||||||
while(bind(socki, (struct sockaddr*)&inaddr, sizeof(inaddr)) < 0) {
|
|
||||||
printf(".");fflush(NULL);
|
|
||||||
usleep(100000);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (listen(socki, 3) != 0) {
|
|
||||||
perror("listen");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
while(1) {
|
|
||||||
accsocket = accept(socki, (struct sockaddr*)&clientaddr, &sin_size);
|
|
||||||
if (accsocket > 0) {
|
|
||||||
//printf("accepted\n");
|
|
||||||
if (!fork())
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
close(accsocket);
|
|
||||||
}
|
}
|
||||||
else if (errno != EINTR) {
|
|
||||||
perror("accept");
|
/* count in options higher than device count ? */
|
||||||
exit(1);
|
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++) {
|
for (i=0; i<currmax; i++) {
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("open %d '%s' m%08X v%08X i%d e%d.\n",
|
printf("open %d '%s' m%08X v%08X i%d e%d.\n",
|
||||||
i, argv[optind+i], mask[i], value[i],
|
i, argv[optind+i], mask[i], value[i],
|
||||||
inv_filter[i], err_mask[i]);
|
inv_filter[i], err_mask[i]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
|
if ((s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
|
||||||
perror("socket");
|
perror("socket");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
|
|
||||||
if (mask[i] || value[i]) {
|
|
||||||
|
|
||||||
printf("CAN ID filter[%d] for %s set to "
|
|
||||||
"mask = %08X, value = %08X %s\n",
|
|
||||||
i, argv[optind+i], mask[i], value[i],
|
|
||||||
(inv_filter[i]) ? "(inv_filter)" : "");
|
|
||||||
|
|
||||||
rfilter.can_id = value[i];
|
|
||||||
rfilter.can_mask = mask[i];
|
|
||||||
if (inv_filter[i])
|
|
||||||
rfilter.can_id |= CAN_INV_FILTER;
|
|
||||||
|
|
||||||
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FILTER,
|
|
||||||
&rfilter, sizeof(rfilter));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err_mask[i])
|
|
||||||
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_ERR_FILTER,
|
|
||||||
&err_mask[i], sizeof(err_mask[i]));
|
|
||||||
|
|
||||||
j = strlen(argv[optind+i]);
|
|
||||||
|
|
||||||
if (!(j < IFNAMSIZ)) {
|
|
||||||
printf("name of CAN device '%s' is too long!\n", argv[optind+i]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (j > max_devname_len)
|
|
||||||
max_devname_len = j; /* for nice printing */
|
|
||||||
|
|
||||||
addr.can_family = AF_CAN;
|
|
||||||
|
|
||||||
if (strcmp(ANYDEV, argv[optind+i])) {
|
|
||||||
strcpy(ifr.ifr_name, argv[optind+i]);
|
|
||||||
if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
|
|
||||||
perror("SIOCGIFINDEX");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
addr.can_ifindex = ifr.ifr_ifindex;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
addr.can_ifindex = 0; /* any can interface */
|
|
||||||
|
|
||||||
if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
||||||
perror("bindcan");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (running) {
|
|
||||||
|
|
||||||
FD_ZERO(&rdfs);
|
|
||||||
for (i=0; i<currmax; i++)
|
|
||||||
FD_SET(s[i], &rdfs);
|
|
||||||
|
|
||||||
if ((ret = select(s[currmax-1]+1, &rdfs, NULL, NULL, NULL)) < 0) {
|
|
||||||
//perror("select");
|
|
||||||
running = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<currmax; i++) { /* check all CAN RAW sockets */
|
|
||||||
|
|
||||||
if (FD_ISSET(s[i], &rdfs)) {
|
|
||||||
|
|
||||||
socklen_t len = sizeof(addr);
|
|
||||||
int idx;
|
|
||||||
|
|
||||||
if ((nbytes = recvfrom(s[i], &frame,
|
|
||||||
sizeof(struct can_frame), 0,
|
|
||||||
(struct sockaddr*)&addr, &len)) < 0) {
|
|
||||||
perror("read");
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbytes < sizeof(struct can_frame)) {
|
if (mask[i] || value[i]) {
|
||||||
fprintf(stderr, "read: incomplete CAN frame\n");
|
|
||||||
return 1;
|
printf("CAN ID filter[%d] for %s set to "
|
||||||
|
"mask = %08X, value = %08X %s\n",
|
||||||
|
i, argv[optind+i], mask[i], value[i],
|
||||||
|
(inv_filter[i]) ? "(inv_filter)" : "");
|
||||||
|
|
||||||
|
rfilter.can_id = value[i];
|
||||||
|
rfilter.can_mask = mask[i];
|
||||||
|
if (inv_filter[i])
|
||||||
|
rfilter.can_id |= CAN_INV_FILTER;
|
||||||
|
|
||||||
|
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FILTER,
|
||||||
|
&rfilter, sizeof(rfilter));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ioctl(s[i], SIOCGSTAMP, &tv) < 0)
|
if (err_mask[i])
|
||||||
perror("SIOCGSTAMP");
|
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_ERR_FILTER,
|
||||||
|
&err_mask[i], sizeof(err_mask[i]));
|
||||||
|
|
||||||
|
j = strlen(argv[optind+i]);
|
||||||
|
|
||||||
idx = idx2dindex(addr.can_ifindex, s[i]);
|
if (!(j < IFNAMSIZ)) {
|
||||||
|
printf("name of CAN device '%s' is too long!\n", argv[optind+i]);
|
||||||
sprintf(temp, "(%ld.%06ld) %*s ",
|
return 1;
|
||||||
tv.tv_sec, tv.tv_usec, max_devname_len, devname[idx]);
|
|
||||||
sprint_canframe(temp+strlen(temp), &frame, 0);
|
|
||||||
strcat(temp, "\n");
|
|
||||||
|
|
||||||
if (write(accsocket, temp, strlen(temp)) < 0) {
|
|
||||||
perror("writeaccsock");
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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); */
|
/* printf("%s\n",temp2); */
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* print CAN frame in log file style to stdout */
|
/* print CAN frame in log file style to stdout */
|
||||||
printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
|
printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
|
||||||
printf("%*s ", max_devname_len, devname[idx]);
|
printf("%*s ", max_devname_len, devname[idx]);
|
||||||
fprint_canframe(stdout, &frame, "\n", 0);
|
fprint_canframe(stdout, &frame, "\n", 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<currmax; i++)
|
for (i=0; i<currmax; i++)
|
||||||
close(s[i]);
|
close(s[i]);
|
||||||
|
|
||||||
close(accsocket);
|
close(accsocket);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
610
canplayer.c
610
canplayer.c
|
|
@ -66,9 +66,9 @@
|
||||||
#define BUFSZ 100 /* for one line in the logfile */
|
#define BUFSZ 100 /* for one line in the logfile */
|
||||||
|
|
||||||
struct assignment {
|
struct assignment {
|
||||||
char txif[IFNAMSIZ];
|
char txif[IFNAMSIZ];
|
||||||
int txifidx;
|
int txifidx;
|
||||||
char rxif[IFNAMSIZ];
|
char rxif[IFNAMSIZ];
|
||||||
};
|
};
|
||||||
static struct assignment asgn[CHANNELS];
|
static struct assignment asgn[CHANNELS];
|
||||||
|
|
||||||
|
|
@ -76,28 +76,28 @@ extern int optind, opterr, optopt;
|
||||||
|
|
||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "\nUsage: %s <options> [interface assignment]*\n\n", prg);
|
fprintf(stderr, "\nUsage: %s <options> [interface assignment]*\n\n", prg);
|
||||||
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
|
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
|
||||||
fprintf(stderr, " -l <num> "
|
fprintf(stderr, " -l <num> "
|
||||||
"(process input file <num> times)\n"
|
"(process input file <num> times)\n"
|
||||||
" "
|
" "
|
||||||
"(Use 'i' for infinite loop - default: %d)\n", DEFAULT_LOOPS);
|
"(Use 'i' for infinite loop - default: %d)\n", DEFAULT_LOOPS);
|
||||||
fprintf(stderr, " -t (ignore timestamps: "
|
fprintf(stderr, " -t (ignore timestamps: "
|
||||||
"send frames immediately)\n");
|
"send frames immediately)\n");
|
||||||
fprintf(stderr, " -g <ms> (gap in milli "
|
fprintf(stderr, " -g <ms> (gap in milli "
|
||||||
"seconds - default: %d ms)\n", DEFAULT_GAP);
|
"seconds - default: %d ms)\n", DEFAULT_GAP);
|
||||||
fprintf(stderr, " -s <s> (skip gaps in "
|
fprintf(stderr, " -s <s> (skip gaps in "
|
||||||
"timestamps > 's' seconds)\n");
|
"timestamps > 's' seconds)\n");
|
||||||
fprintf(stderr, " -x (disable local "
|
fprintf(stderr, " -x (disable local "
|
||||||
"loopback of sent CAN frames)\n");
|
"loopback of sent CAN frames)\n");
|
||||||
fprintf(stderr, " -v (verbose: print "
|
fprintf(stderr, " -v (verbose: print "
|
||||||
"sent CAN frames)\n\n");
|
"sent CAN frames)\n\n");
|
||||||
fprintf(stderr, "Interface assignment: 0..n assignments like "
|
fprintf(stderr, "Interface assignment: 0..n assignments like "
|
||||||
"<write-if>=<log-if>\n");
|
"<write-if>=<log-if>\n");
|
||||||
fprintf(stderr, "e.g. vcan2=can0 ( send frames received from can0 on "
|
fprintf(stderr, "e.g. vcan2=can0 ( send frames received from can0 on "
|
||||||
"vcan2 )\n");
|
"vcan2 )\n");
|
||||||
fprintf(stderr, "No assignments => send frames to the interface(s) they "
|
fprintf(stderr, "No assignments => send frames to the interface(s) they "
|
||||||
"had been received from.\n\n");
|
"had been received from.\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copied from /usr/src/linux/include/linux/time.h ...
|
/* copied from /usr/src/linux/include/linux/time.h ...
|
||||||
|
|
@ -107,367 +107,367 @@ void print_usage(char *prg)
|
||||||
*/
|
*/
|
||||||
static inline int timeval_compare(struct timeval *lhs, struct timeval *rhs)
|
static inline int timeval_compare(struct timeval *lhs, struct timeval *rhs)
|
||||||
{
|
{
|
||||||
if (lhs->tv_sec < rhs->tv_sec)
|
if (lhs->tv_sec < rhs->tv_sec)
|
||||||
return -1;
|
return -1;
|
||||||
if (lhs->tv_sec > rhs->tv_sec)
|
if (lhs->tv_sec > rhs->tv_sec)
|
||||||
return 1;
|
return 1;
|
||||||
return lhs->tv_usec - rhs->tv_usec;
|
return lhs->tv_usec - rhs->tv_usec;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void create_diff_tv(struct timeval *today, struct timeval *diff,
|
static inline void create_diff_tv(struct timeval *today, struct timeval *diff,
|
||||||
struct timeval *log) {
|
struct timeval *log) {
|
||||||
|
|
||||||
/* create diff_tv so that log_tv + diff_tv = today_tv */
|
/* create diff_tv so that log_tv + diff_tv = today_tv */
|
||||||
diff->tv_sec = today->tv_sec - log->tv_sec;
|
diff->tv_sec = today->tv_sec - log->tv_sec;
|
||||||
diff->tv_usec = today->tv_usec - log->tv_usec;
|
diff->tv_usec = today->tv_usec - log->tv_usec;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int frames_to_send(struct timeval *today, struct timeval *diff,
|
static inline int frames_to_send(struct timeval *today, struct timeval *diff,
|
||||||
struct timeval *log)
|
struct timeval *log)
|
||||||
{
|
{
|
||||||
/* return value <0 when log + diff < today */
|
/* return value <0 when log + diff < today */
|
||||||
|
|
||||||
struct timeval cmp;
|
struct timeval cmp;
|
||||||
|
|
||||||
cmp.tv_sec = log->tv_sec + diff->tv_sec;
|
cmp.tv_sec = log->tv_sec + diff->tv_sec;
|
||||||
cmp.tv_usec = log->tv_usec + diff->tv_usec;
|
cmp.tv_usec = log->tv_usec + diff->tv_usec;
|
||||||
|
|
||||||
if (cmp.tv_usec > 1000000) {
|
if (cmp.tv_usec > 1000000) {
|
||||||
cmp.tv_usec -= 1000000;
|
cmp.tv_usec -= 1000000;
|
||||||
cmp.tv_sec++;
|
cmp.tv_sec++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmp.tv_usec < 0) {
|
if (cmp.tv_usec < 0) {
|
||||||
cmp.tv_usec += 1000000;
|
cmp.tv_usec += 1000000;
|
||||||
cmp.tv_sec--;
|
cmp.tv_sec--;
|
||||||
}
|
}
|
||||||
|
|
||||||
return timeval_compare(&cmp, today);
|
return timeval_compare(&cmp, today);
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_txidx(char *logif_name) {
|
int get_txidx(char *logif_name) {
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i=0; i<CHANNELS; i++) {
|
for (i=0; i<CHANNELS; i++) {
|
||||||
if (asgn[i].rxif[0] == 0) /* end of table content */
|
if (asgn[i].rxif[0] == 0) /* end of table content */
|
||||||
break;
|
break;
|
||||||
if (strcmp(asgn[i].rxif, logif_name) == 0) /* found device name */
|
if (strcmp(asgn[i].rxif, logif_name) == 0) /* found device name */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((i == CHANNELS) || (asgn[i].rxif[0] == 0))
|
if ((i == CHANNELS) || (asgn[i].rxif[0] == 0))
|
||||||
return 0; /* not found */
|
return 0; /* not found */
|
||||||
|
|
||||||
return asgn[i].txifidx; /* return interface index */
|
return asgn[i].txifidx; /* return interface index */
|
||||||
}
|
}
|
||||||
|
|
||||||
char *get_txname(char *logif_name) {
|
char *get_txname(char *logif_name) {
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i=0; i<CHANNELS; i++) {
|
for (i=0; i<CHANNELS; i++) {
|
||||||
if (asgn[i].rxif[0] == 0) /* end of table content */
|
if (asgn[i].rxif[0] == 0) /* end of table content */
|
||||||
break;
|
break;
|
||||||
if (strcmp(asgn[i].rxif, logif_name) == 0) /* found device name */
|
if (strcmp(asgn[i].rxif, logif_name) == 0) /* found device name */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((i == CHANNELS) || (asgn[i].rxif[0] == 0))
|
if ((i == CHANNELS) || (asgn[i].rxif[0] == 0))
|
||||||
return 0; /* not found */
|
return 0; /* not found */
|
||||||
|
|
||||||
return asgn[i].txif; /* return interface name */
|
return asgn[i].txif; /* return interface name */
|
||||||
}
|
}
|
||||||
|
|
||||||
int add_assignment(char *mode, int socket, char *txname, char *rxname,
|
int add_assignment(char *mode, int socket, char *txname, char *rxname,
|
||||||
int verbose) {
|
int verbose) {
|
||||||
|
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* find free entry */
|
/* find free entry */
|
||||||
for (i=0; i<CHANNELS; i++) {
|
for (i=0; i<CHANNELS; i++) {
|
||||||
if (asgn[i].txif[0] == 0)
|
if (asgn[i].txif[0] == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == CHANNELS) {
|
if (i == CHANNELS) {
|
||||||
fprintf(stderr, "Assignment table exceeded!\n");
|
fprintf(stderr, "Assignment table exceeded!\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(txname) >= IFNAMSIZ) {
|
if (strlen(txname) >= IFNAMSIZ) {
|
||||||
fprintf(stderr, "write-if interface name '%s' too long!", txname);
|
fprintf(stderr, "write-if interface name '%s' too long!", txname);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
strcpy(asgn[i].txif, txname);
|
strcpy(asgn[i].txif, txname);
|
||||||
|
|
||||||
if (strlen(rxname) >= IFNAMSIZ) {
|
if (strlen(rxname) >= IFNAMSIZ) {
|
||||||
fprintf(stderr, "log-if interface name '%s' too long!", rxname);
|
fprintf(stderr, "log-if interface name '%s' too long!", rxname);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
strcpy(asgn[i].rxif, rxname);
|
strcpy(asgn[i].rxif, rxname);
|
||||||
|
|
||||||
strcpy(ifr.ifr_name, txname);
|
strcpy(ifr.ifr_name, txname);
|
||||||
if (ioctl(socket, SIOCGIFINDEX, &ifr) < 0) {
|
if (ioctl(socket, SIOCGIFINDEX, &ifr) < 0) {
|
||||||
perror("SIOCGIFINDEX");
|
perror("SIOCGIFINDEX");
|
||||||
fprintf(stderr, "write-if interface name '%s' is wrong!\n", txname);
|
fprintf(stderr, "write-if interface name '%s' is wrong!\n", txname);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
asgn[i].txifidx = ifr.ifr_ifindex;
|
asgn[i].txifidx = ifr.ifr_ifindex;
|
||||||
|
|
||||||
if (verbose > 1) /* use -v -v to see this */
|
if (verbose > 1) /* use -v -v to see this */
|
||||||
printf("added %s assignment: log-if=%s write-if=%s write-if-idx=%d\n",
|
printf("added %s assignment: log-if=%s write-if=%s write-if-idx=%d\n",
|
||||||
mode, asgn[i].rxif, asgn[i].txif, asgn[i].txifidx);
|
mode, asgn[i].rxif, asgn[i].txif, asgn[i].txifidx);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
static char buf[BUFSZ], device[BUFSZ], ascframe[BUFSZ];
|
static char buf[BUFSZ], device[BUFSZ], ascframe[BUFSZ];
|
||||||
struct sockaddr_can addr;
|
struct sockaddr_can addr;
|
||||||
static struct can_frame frame;
|
static struct can_frame frame;
|
||||||
static struct timeval today_tv, log_tv, last_log_tv, diff_tv;
|
static struct timeval today_tv, log_tv, last_log_tv, diff_tv;
|
||||||
struct timespec sleep_ts;
|
struct timespec sleep_ts;
|
||||||
int s; /* CAN_RAW socket */
|
int s; /* CAN_RAW socket */
|
||||||
FILE *infile = stdin;
|
FILE *infile = stdin;
|
||||||
unsigned long gap = DEFAULT_GAP;
|
unsigned long gap = DEFAULT_GAP;
|
||||||
int use_timestamps = 1;
|
int use_timestamps = 1;
|
||||||
static int verbose, opt, delay_loops, skipgap;
|
static int verbose, opt, delay_loops, skipgap;
|
||||||
static int loopback_disable = 0;
|
static int loopback_disable = 0;
|
||||||
static int infinite_loops = 0;
|
static int infinite_loops = 0;
|
||||||
static int loops = DEFAULT_LOOPS;
|
static int loops = DEFAULT_LOOPS;
|
||||||
int assignments; /* assignments defined on the commandline */
|
int assignments; /* assignments defined on the commandline */
|
||||||
int txidx; /* sendto() interface index */
|
int txidx; /* sendto() interface index */
|
||||||
int eof, nbytes, i, j;
|
int eof, nbytes, i, j;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "I:l:tg:s:xv")) != -1) {
|
while ((opt = getopt(argc, argv, "I:l:tg:s:xv")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'I':
|
case 'I':
|
||||||
infile = fopen(optarg, "r");
|
infile = fopen(optarg, "r");
|
||||||
if (!infile) {
|
if (!infile) {
|
||||||
perror("infile");
|
perror("infile");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
if (optarg[0] == 'i')
|
if (optarg[0] == 'i')
|
||||||
infinite_loops = 1;
|
infinite_loops = 1;
|
||||||
else
|
else
|
||||||
if (!(loops = atoi(optarg))) {
|
if (!(loops = atoi(optarg))) {
|
||||||
fprintf(stderr, "Invalid argument for option -l !\n");
|
fprintf(stderr, "Invalid argument for option -l !\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 't':
|
||||||
|
use_timestamps = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'g':
|
||||||
|
gap = strtoul(optarg, NULL, 10);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
skipgap = strtoul(optarg, NULL, 10);
|
||||||
|
if (skipgap < 1) {
|
||||||
|
fprintf(stderr, "Invalid argument for option -s !\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'x':
|
||||||
|
loopback_disable = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'v':
|
||||||
|
verbose++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
print_usage(basename(argv[0]));
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case 't':
|
|
||||||
use_timestamps = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'g':
|
|
||||||
gap = strtoul(optarg, NULL, 10);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 's':
|
|
||||||
skipgap = strtoul(optarg, NULL, 10);
|
|
||||||
if (skipgap < 1) {
|
|
||||||
fprintf(stderr, "Invalid argument for option -s !\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'x':
|
|
||||||
loopback_disable = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'v':
|
|
||||||
verbose++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
print_usage(basename(argv[0]));
|
|
||||||
return 1;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
assignments = argc - optind; /* find real number of user assignments */
|
assignments = argc - optind; /* find real number of user assignments */
|
||||||
|
|
||||||
if (infile == stdin) { /* no jokes with stdin */
|
if (infile == stdin) { /* no jokes with stdin */
|
||||||
infinite_loops = 0;
|
infinite_loops = 0;
|
||||||
loops = 1;
|
loops = 1;
|
||||||
}
|
|
||||||
|
|
||||||
if (verbose > 1) /* use -v -v to see this */
|
|
||||||
if (infinite_loops)
|
|
||||||
printf("infinite_loops\n");
|
|
||||||
else
|
|
||||||
printf("%d loops\n", loops);
|
|
||||||
|
|
||||||
sleep_ts.tv_sec = gap / 1000;
|
|
||||||
sleep_ts.tv_nsec = (gap % 1000) * 1000000;
|
|
||||||
|
|
||||||
/* open socket */
|
|
||||||
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
|
|
||||||
perror("socket");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr.can_family = AF_CAN;
|
|
||||||
addr.can_ifindex = 0;
|
|
||||||
|
|
||||||
/* disable unneeded default receive filter on this RAW socket */
|
|
||||||
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
|
|
||||||
|
|
||||||
if (loopback_disable) {
|
|
||||||
int loopback = 0;
|
|
||||||
|
|
||||||
setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
|
|
||||||
&loopback, sizeof(loopback));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
||||||
perror("bind");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (assignments) {
|
|
||||||
/* add & check user assginments from commandline */
|
|
||||||
for (i=0; i<assignments; i++) {
|
|
||||||
if (strlen(argv[optind+i]) >= BUFSZ) {
|
|
||||||
fprintf(stderr, "Assignment too long!\n");
|
|
||||||
print_usage(basename(argv[0]));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
strcpy(buf, argv[optind+i]);
|
|
||||||
for (j=0; j<BUFSZ; j++) { /* find '=' in assignment */
|
|
||||||
if (buf[j] == '=')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (buf[j] != '=') {
|
|
||||||
fprintf(stderr, "'=' missing in assignment!\n");
|
|
||||||
print_usage(basename(argv[0]));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
buf[j] = 0; /* cut string in two pieces */
|
|
||||||
if (add_assignment("user", s, &buf[0], &buf[j+1], verbose))
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
while (infinite_loops || loops--) {
|
|
||||||
|
|
||||||
if (infile != stdin)
|
|
||||||
rewind(infile); /* for each loop */
|
|
||||||
|
|
||||||
if (verbose > 1) /* use -v -v to see this */
|
if (verbose > 1) /* use -v -v to see this */
|
||||||
printf (">>>>>>>>> start reading file. remaining loops = %d\n", loops);
|
if (infinite_loops)
|
||||||
|
printf("infinite_loops\n");
|
||||||
|
else
|
||||||
|
printf("%d loops\n", loops);
|
||||||
|
|
||||||
if (!fgets(buf, BUFSZ-1, infile)) /* read first frame from logfile */
|
sleep_ts.tv_sec = gap / 1000;
|
||||||
goto out; /* nothing to read */
|
sleep_ts.tv_nsec = (gap % 1000) * 1000000;
|
||||||
|
|
||||||
eof = 0;
|
/* open socket */
|
||||||
|
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
|
||||||
if (sscanf(buf, "(%ld.%ld) %s %s", &log_tv.tv_sec, &log_tv.tv_usec,
|
perror("socket");
|
||||||
device, ascframe) != 4)
|
return 1;
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (use_timestamps) { /* throttle sending due to logfile timestamps */
|
|
||||||
|
|
||||||
gettimeofday(&today_tv, NULL);
|
|
||||||
create_diff_tv(&today_tv, &diff_tv, &log_tv);
|
|
||||||
last_log_tv = log_tv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!eof) {
|
addr.can_family = AF_CAN;
|
||||||
|
addr.can_ifindex = 0;
|
||||||
|
|
||||||
while ((!use_timestamps) ||
|
/* disable unneeded default receive filter on this RAW socket */
|
||||||
(frames_to_send(&today_tv, &diff_tv, &log_tv) < 0)) {
|
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
|
||||||
|
|
||||||
/* log_tv/device/ascframe are valid here */
|
if (loopback_disable) {
|
||||||
|
int loopback = 0;
|
||||||
|
|
||||||
if (strlen(device) >= IFNAMSIZ) {
|
setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
|
||||||
fprintf(stderr, "log interface name '%s' too long!", device);
|
&loopback, sizeof(loopback));
|
||||||
return 1;
|
}
|
||||||
|
|
||||||
|
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||||
|
perror("bind");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (assignments) {
|
||||||
|
/* add & check user assginments from commandline */
|
||||||
|
for (i=0; i<assignments; i++) {
|
||||||
|
if (strlen(argv[optind+i]) >= BUFSZ) {
|
||||||
|
fprintf(stderr, "Assignment too long!\n");
|
||||||
|
print_usage(basename(argv[0]));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
strcpy(buf, argv[optind+i]);
|
||||||
|
for (j=0; j<BUFSZ; j++) { /* find '=' in assignment */
|
||||||
|
if (buf[j] == '=')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (buf[j] != '=') {
|
||||||
|
fprintf(stderr, "'=' missing in assignment!\n");
|
||||||
|
print_usage(basename(argv[0]));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
buf[j] = 0; /* cut string in two pieces */
|
||||||
|
if (add_assignment("user", s, &buf[0], &buf[j+1], verbose))
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
txidx = get_txidx(device); /* get ifindex for sending the frame */
|
while (infinite_loops || loops--) {
|
||||||
|
|
||||||
if ((!txidx) && (!assignments)) {
|
|
||||||
/* 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 (txidx) { /* only send to valid CAN devices */
|
if (infile != stdin)
|
||||||
|
rewind(infile); /* for each loop */
|
||||||
|
|
||||||
if (parse_canframe(ascframe, &frame)) {
|
if (verbose > 1) /* use -v -v to see this */
|
||||||
fprintf(stderr, "wrong CAN frame format: '%s'!", ascframe);
|
printf (">>>>>>>>> start reading file. remaining loops = %d\n", loops);
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr.can_family = AF_CAN;
|
if (!fgets(buf, BUFSZ-1, infile)) /* read first frame from logfile */
|
||||||
addr.can_ifindex = txidx; /* send via this interface */
|
goto out; /* nothing to read */
|
||||||
|
|
||||||
nbytes = sendto(s, &frame, sizeof(struct can_frame), 0,
|
|
||||||
(struct sockaddr*)&addr, sizeof(addr));
|
|
||||||
|
|
||||||
if (nbytes != sizeof(struct can_frame)) {
|
eof = 0;
|
||||||
perror("sendto");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (verbose) {
|
|
||||||
printf("%s (%s) ", get_txname(device), device);
|
|
||||||
fprint_long_canframe(stdout, &frame, "\n", 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* read next frame from logfile */
|
|
||||||
if (!fgets(buf, BUFSZ-1, infile)) {
|
|
||||||
eof = 1; /* this file is completely processed */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sscanf(buf, "(%ld.%ld) %s %s", &log_tv.tv_sec, &log_tv.tv_usec,
|
if (sscanf(buf, "(%ld.%ld) %s %s", &log_tv.tv_sec, &log_tv.tv_usec,
|
||||||
device, ascframe) != 4)
|
device, ascframe) != 4)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (use_timestamps) {
|
if (use_timestamps) { /* throttle sending due to logfile timestamps */
|
||||||
gettimeofday(&today_tv, NULL);
|
|
||||||
|
|
||||||
/* test for logfile timestamps jumping backwards OR */
|
gettimeofday(&today_tv, NULL);
|
||||||
/* if the user likes to skip long gaps in the timestamps */
|
|
||||||
if ((last_log_tv.tv_sec > log_tv.tv_sec) ||
|
|
||||||
(skipgap && abs(last_log_tv.tv_sec - log_tv.tv_sec) > skipgap))
|
|
||||||
create_diff_tv(&today_tv, &diff_tv, &log_tv);
|
create_diff_tv(&today_tv, &diff_tv, &log_tv);
|
||||||
|
last_log_tv = log_tv;
|
||||||
last_log_tv = log_tv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* while frames_to_send ... */
|
while (!eof) {
|
||||||
|
|
||||||
if (nanosleep(&sleep_ts, NULL))
|
while ((!use_timestamps) ||
|
||||||
return 1;
|
(frames_to_send(&today_tv, &diff_tv, &log_tv) < 0)) {
|
||||||
|
|
||||||
delay_loops++; /* private statistics */
|
/* log_tv/device/ascframe are valid here */
|
||||||
gettimeofday(&today_tv, NULL);
|
|
||||||
|
|
||||||
} /* while (!eof) */
|
if (strlen(device) >= IFNAMSIZ) {
|
||||||
|
fprintf(stderr, "log interface name '%s' too long!", device);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
} /* while (infinite_loops || loops--) */
|
txidx = get_txidx(device); /* get ifindex for sending the frame */
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
if (txidx) { /* only send to valid CAN devices */
|
||||||
|
|
||||||
close(s);
|
if (parse_canframe(ascframe, &frame)) {
|
||||||
fclose(infile);
|
fprintf(stderr, "wrong CAN frame format: '%s'!", ascframe);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (verbose > 1) /* use -v -v to see this */
|
addr.can_family = AF_CAN;
|
||||||
printf("%d delay_loops\n", delay_loops);
|
addr.can_ifindex = txidx; /* send via this interface */
|
||||||
|
|
||||||
|
nbytes = sendto(s, &frame, sizeof(struct can_frame), 0,
|
||||||
|
(struct sockaddr*)&addr, sizeof(addr));
|
||||||
|
|
||||||
return 0;
|
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
102
cansend.c
|
|
@ -60,66 +60,66 @@
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int s; /* can raw socket */
|
int s; /* can raw socket */
|
||||||
int nbytes;
|
int nbytes;
|
||||||
struct sockaddr_can addr;
|
struct sockaddr_can addr;
|
||||||
struct can_frame frame;
|
struct can_frame frame;
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
|
|
||||||
/* check command line options */
|
/* check command line options */
|
||||||
if (argc != 3) {
|
if (argc != 3) {
|
||||||
fprintf(stderr, "Usage: %s <device> <can_frame>.\n", argv[0]);
|
fprintf(stderr, "Usage: %s <device> <can_frame>.\n", argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse CAN frame */
|
/* parse CAN frame */
|
||||||
if (parse_canframe(argv[2], &frame)){
|
if (parse_canframe(argv[2], &frame)){
|
||||||
fprintf(stderr, "\nWrong CAN-frame format!\n\n");
|
fprintf(stderr, "\nWrong CAN-frame format!\n\n");
|
||||||
fprintf(stderr, "Try: <can_id>#{R|data}\n");
|
fprintf(stderr, "Try: <can_id>#{R|data}\n");
|
||||||
fprintf(stderr, "can_id can have 3 (SFF) or 8 (EFF) hex chars\n");
|
fprintf(stderr, "can_id can have 3 (SFF) or 8 (EFF) hex chars\n");
|
||||||
fprintf(stderr, "data has 0 to 8 hex-values that can (optionally)");
|
fprintf(stderr, "data has 0 to 8 hex-values that can (optionally)");
|
||||||
fprintf(stderr, " be seperated by '.'\n\n");
|
fprintf(stderr, " be seperated by '.'\n\n");
|
||||||
fprintf(stderr, "e.g. 5A1#11.2233.44556677.88 / 123#DEADBEEF / ");
|
fprintf(stderr, "e.g. 5A1#11.2233.44556677.88 / 123#DEADBEEF / ");
|
||||||
fprintf(stderr, "5AA# /\n 1F334455#1122334455667788 / 123#R ");
|
fprintf(stderr, "5AA# /\n 1F334455#1122334455667788 / 123#R ");
|
||||||
fprintf(stderr, "for remote transmission request.\n\n");
|
fprintf(stderr, "for remote transmission request.\n\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* open socket */
|
/* open socket */
|
||||||
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
|
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
|
||||||
perror("socket");
|
perror("socket");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
addr.can_family = AF_CAN;
|
addr.can_family = AF_CAN;
|
||||||
|
|
||||||
strcpy(ifr.ifr_name, argv[1]);
|
strcpy(ifr.ifr_name, argv[1]);
|
||||||
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
|
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
|
||||||
perror("SIOCGIFINDEX");
|
perror("SIOCGIFINDEX");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
addr.can_ifindex = ifr.ifr_ifindex;
|
addr.can_ifindex = ifr.ifr_ifindex;
|
||||||
|
|
||||||
/* disable default receive filter on this RAW socket */
|
/* disable default receive filter on this RAW socket */
|
||||||
/* This is obsolete as we do not read from the socket at all, but for */
|
/* This is obsolete as we do not read from the socket at all, but for */
|
||||||
/* this reason we can remove the receive list in the Kernel to save a */
|
/* this reason we can remove the receive list in the Kernel to save a */
|
||||||
/* little (really a very little!) CPU usage. */
|
/* little (really a very little!) CPU usage. */
|
||||||
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
|
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
|
||||||
|
|
||||||
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||||
perror("bind");
|
perror("bind");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send frame */
|
/* send frame */
|
||||||
if ((nbytes = write(s, &frame, sizeof(frame))) != sizeof(frame)) {
|
if ((nbytes = write(s, &frame, sizeof(frame))) != sizeof(frame)) {
|
||||||
perror("write");
|
perror("write");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//fprint_long_canframe(stdout, &frame, "\n", 0);
|
//fprint_long_canframe(stdout, &frame, "\n", 0);
|
||||||
|
|
||||||
close(s);
|
close(s);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1020
cansniffer.c
1020
cansniffer.c
File diff suppressed because it is too large
Load Diff
278
lib.c
278
lib.c
|
|
@ -61,187 +61,187 @@
|
||||||
|
|
||||||
static int asc2nibble(char c) {
|
static int asc2nibble(char c) {
|
||||||
|
|
||||||
if ((c >= '0') && (c <= '9'))
|
if ((c >= '0') && (c <= '9'))
|
||||||
return c - '0';
|
return c - '0';
|
||||||
|
|
||||||
if ((c >= 'A') && (c <= 'F'))
|
if ((c >= 'A') && (c <= 'F'))
|
||||||
return c - 'A' + 10;
|
return c - 'A' + 10;
|
||||||
|
|
||||||
if ((c >= 'a') && (c <= 'f'))
|
if ((c >= 'a') && (c <= 'f'))
|
||||||
return c - 'a' + 10;
|
return c - 'a' + 10;
|
||||||
|
|
||||||
return 16; /* error */
|
return 16; /* error */
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_canframe(char *cs, struct can_frame *cf) {
|
int parse_canframe(char *cs, struct can_frame *cf) {
|
||||||
/* documentation see lib.h */
|
/* documentation see lib.h */
|
||||||
|
|
||||||
int i, idx, dlc, len, tmp;
|
int i, idx, dlc, len, tmp;
|
||||||
|
|
||||||
len = strlen(cs);
|
len = strlen(cs);
|
||||||
//printf("'%s' len %d\n", cs, len);
|
//printf("'%s' len %d\n", cs, len);
|
||||||
|
|
||||||
memset(cf, 0, sizeof(*cf)); /* init CAN frame, e.g. DLC = 0 */
|
memset(cf, 0, sizeof(*cf)); /* init CAN frame, e.g. DLC = 0 */
|
||||||
|
|
||||||
if (len < 4)
|
if (len < 4)
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (!((cs[3] == CANID_DELIM) || (cs[8] == CANID_DELIM)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (cs[8] == CANID_DELIM) { /* 8 digits */
|
|
||||||
|
|
||||||
idx = 9;
|
|
||||||
for (i=0; i<8; i++){
|
|
||||||
if ((tmp = asc2nibble(cs[i])) > 0x0F)
|
|
||||||
return 1;
|
return 1;
|
||||||
cf->can_id |= (tmp << (7-i)*4);
|
|
||||||
}
|
|
||||||
if (!(cf->can_id & CAN_ERR_FLAG)) /* 8 digits but no errorframe? */
|
|
||||||
cf->can_id |= CAN_EFF_FLAG; /* then it is an extended frame */
|
|
||||||
|
|
||||||
} else { /* 3 digits */
|
if (!((cs[3] == CANID_DELIM) || (cs[8] == CANID_DELIM)))
|
||||||
|
|
||||||
idx = 4;
|
|
||||||
for (i=0; i<3; i++){
|
|
||||||
if ((tmp = asc2nibble(cs[i])) > 0x0F)
|
|
||||||
return 1;
|
return 1;
|
||||||
cf->can_id |= (tmp << (2-i)*4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if((cs[idx] == 'R') || (cs[idx] == 'r')){ /* RTR frame */
|
if (cs[8] == CANID_DELIM) { /* 8 digits */
|
||||||
cf->can_id |= CAN_RTR_FLAG;
|
|
||||||
|
idx = 9;
|
||||||
|
for (i=0; i<8; i++){
|
||||||
|
if ((tmp = asc2nibble(cs[i])) > 0x0F)
|
||||||
|
return 1;
|
||||||
|
cf->can_id |= (tmp << (7-i)*4);
|
||||||
|
}
|
||||||
|
if (!(cf->can_id & CAN_ERR_FLAG)) /* 8 digits but no errorframe? */
|
||||||
|
cf->can_id |= CAN_EFF_FLAG; /* then it is an extended frame */
|
||||||
|
|
||||||
|
} else { /* 3 digits */
|
||||||
|
|
||||||
|
idx = 4;
|
||||||
|
for (i=0; i<3; i++){
|
||||||
|
if ((tmp = asc2nibble(cs[i])) > 0x0F)
|
||||||
|
return 1;
|
||||||
|
cf->can_id |= (tmp << (2-i)*4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if((cs[idx] == 'R') || (cs[idx] == 'r')){ /* RTR frame */
|
||||||
|
cf->can_id |= CAN_RTR_FLAG;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0, dlc=0; i<8; i++){
|
||||||
|
|
||||||
|
if(cs[idx] == DATA_SEPERATOR) /* skip (optional) seperator */
|
||||||
|
idx++;
|
||||||
|
|
||||||
|
if(idx >= len) /* end of string => end of data */
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ((tmp = asc2nibble(cs[idx++])) > 0x0F)
|
||||||
|
return 1;
|
||||||
|
cf->data[i] = (tmp << 4);
|
||||||
|
if ((tmp = asc2nibble(cs[idx++])) > 0x0F)
|
||||||
|
return 1;
|
||||||
|
cf->data[i] |= tmp;
|
||||||
|
dlc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
cf->can_dlc = dlc;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0, dlc=0; i<8; i++){
|
|
||||||
|
|
||||||
if(cs[idx] == DATA_SEPERATOR) /* skip (optional) seperator */
|
|
||||||
idx++;
|
|
||||||
|
|
||||||
if(idx >= len) /* end of string => end of data */
|
|
||||||
break;
|
|
||||||
|
|
||||||
if ((tmp = asc2nibble(cs[idx++])) > 0x0F)
|
|
||||||
return 1;
|
|
||||||
cf->data[i] = (tmp << 4);
|
|
||||||
if ((tmp = asc2nibble(cs[idx++])) > 0x0F)
|
|
||||||
return 1;
|
|
||||||
cf->data[i] |= tmp;
|
|
||||||
dlc++;
|
|
||||||
}
|
|
||||||
|
|
||||||
cf->can_dlc = dlc;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void fprint_canframe(FILE *stream , struct can_frame *cf, char *eol, int sep) {
|
void fprint_canframe(FILE *stream , struct can_frame *cf, char *eol, int sep) {
|
||||||
/* documentation see lib.h */
|
/* documentation see lib.h */
|
||||||
|
|
||||||
char buf[sizeof(MAX_CANFRAME)+1]; /* max length */
|
char buf[sizeof(MAX_CANFRAME)+1]; /* max length */
|
||||||
|
|
||||||
sprint_canframe(buf, cf, sep);
|
sprint_canframe(buf, cf, sep);
|
||||||
fprintf(stream, "%s", buf);
|
fprintf(stream, "%s", buf);
|
||||||
if (eol)
|
if (eol)
|
||||||
fprintf(stream, "%s", eol);
|
fprintf(stream, "%s", eol);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sprint_canframe(char *buf , struct can_frame *cf, int sep) {
|
void sprint_canframe(char *buf , struct can_frame *cf, int sep) {
|
||||||
/* documentation see lib.h */
|
/* documentation see lib.h */
|
||||||
|
|
||||||
int i,offset;
|
int i,offset;
|
||||||
|
|
||||||
if (cf->can_id & CAN_ERR_FLAG) {
|
if (cf->can_id & CAN_ERR_FLAG) {
|
||||||
sprintf(buf, "%08X#", cf->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG));
|
sprintf(buf, "%08X#", cf->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG));
|
||||||
offset = 9;
|
offset = 9;
|
||||||
} else if (cf->can_id & CAN_EFF_FLAG) {
|
} else if (cf->can_id & CAN_EFF_FLAG) {
|
||||||
sprintf(buf, "%08X#", cf->can_id & CAN_EFF_MASK);
|
sprintf(buf, "%08X#", cf->can_id & CAN_EFF_MASK);
|
||||||
offset = 9;
|
offset = 9;
|
||||||
} else {
|
} else {
|
||||||
sprintf(buf, "%03X#", cf->can_id & CAN_SFF_MASK);
|
sprintf(buf, "%03X#", cf->can_id & CAN_SFF_MASK);
|
||||||
offset = 4;
|
offset = 4;
|
||||||
}
|
|
||||||
|
|
||||||
if (cf->can_id & CAN_RTR_FLAG) /* there are no ERR frames with RTR */
|
|
||||||
sprintf(buf+offset, "R");
|
|
||||||
else
|
|
||||||
for (i = 0; i < cf->can_dlc; i++) {
|
|
||||||
sprintf(buf+offset, "%02X", cf->data[i]);
|
|
||||||
offset += 2;
|
|
||||||
if (sep && (i+1 < cf->can_dlc))
|
|
||||||
sprintf(buf+offset++, ".");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cf->can_id & CAN_RTR_FLAG) /* there are no ERR frames with RTR */
|
||||||
|
sprintf(buf+offset, "R");
|
||||||
|
else
|
||||||
|
for (i = 0; i < cf->can_dlc; i++) {
|
||||||
|
sprintf(buf+offset, "%02X", cf->data[i]);
|
||||||
|
offset += 2;
|
||||||
|
if (sep && (i+1 < cf->can_dlc))
|
||||||
|
sprintf(buf+offset++, ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void fprint_long_canframe(FILE *stream , struct can_frame *cf, char *eol, int view) {
|
void fprint_long_canframe(FILE *stream , struct can_frame *cf, char *eol, int view) {
|
||||||
/* documentation see lib.h */
|
/* documentation see lib.h */
|
||||||
|
|
||||||
char buf[sizeof(MAX_LONG_CANFRAME)+1]; /* max length */
|
char buf[sizeof(MAX_LONG_CANFRAME)+1]; /* max length */
|
||||||
|
|
||||||
sprint_long_canframe(buf, cf, view);
|
sprint_long_canframe(buf, cf, view);
|
||||||
fprintf(stream, "%s", buf);
|
fprintf(stream, "%s", buf);
|
||||||
if (eol)
|
if (eol)
|
||||||
fprintf(stream, "%s", eol);
|
fprintf(stream, "%s", eol);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sprint_long_canframe(char *buf , struct can_frame *cf, int view) {
|
void sprint_long_canframe(char *buf , struct can_frame *cf, int view) {
|
||||||
/* documentation see lib.h */
|
/* documentation see lib.h */
|
||||||
|
|
||||||
int i, j, dlen, offset;
|
int i, j, dlen, offset;
|
||||||
|
|
||||||
if (cf->can_id & CAN_ERR_FLAG) {
|
if (cf->can_id & CAN_ERR_FLAG) {
|
||||||
sprintf(buf, "%8X ", cf->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG));
|
sprintf(buf, "%8X ", cf->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG));
|
||||||
offset = 10;
|
offset = 10;
|
||||||
} else if (cf->can_id & CAN_EFF_FLAG) {
|
} else if (cf->can_id & CAN_EFF_FLAG) {
|
||||||
sprintf(buf, "%8X ", cf->can_id & CAN_EFF_MASK);
|
sprintf(buf, "%8X ", cf->can_id & CAN_EFF_MASK);
|
||||||
offset = 10;
|
offset = 10;
|
||||||
} else {
|
} else {
|
||||||
sprintf(buf, "%3X ", cf->can_id & CAN_SFF_MASK);
|
sprintf(buf, "%3X ", cf->can_id & CAN_SFF_MASK);
|
||||||
offset = 5;
|
offset = 5;
|
||||||
}
|
|
||||||
|
|
||||||
sprintf(buf+offset, "[%d]", cf->can_dlc);
|
|
||||||
offset += 3;
|
|
||||||
|
|
||||||
if (cf->can_id & CAN_RTR_FLAG) { /* there are no ERR frames with RTR */
|
|
||||||
sprintf(buf+offset, " remote request");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (view & CANLIB_VIEW_BINARY) {
|
|
||||||
dlen = 9; /* _10101010 */
|
|
||||||
for (i = 0; i < cf->can_dlc; i++) {
|
|
||||||
buf[offset++] = ' ';
|
|
||||||
for (j = 7; j >= 0; j--)
|
|
||||||
buf[offset++] = (1<<j & cf->data[i])?'1':'0';
|
|
||||||
}
|
}
|
||||||
buf[offset] = 0; /* terminate string */
|
|
||||||
} else {
|
sprintf(buf+offset, "[%d]", cf->can_dlc);
|
||||||
dlen = 3; /* _AA */
|
offset += 3;
|
||||||
for (i = 0; i < cf->can_dlc; i++) {
|
|
||||||
sprintf(buf+offset, " %02X", cf->data[i]);
|
if (cf->can_id & CAN_RTR_FLAG) { /* there are no ERR frames with RTR */
|
||||||
offset += dlen;
|
sprintf(buf+offset, " remote request");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (cf->can_id & CAN_ERR_FLAG)
|
if (view & CANLIB_VIEW_BINARY) {
|
||||||
sprintf(buf+offset, "%*s", dlen*(8-cf->can_dlc)+13, "ERRORFRAME");
|
dlen = 9; /* _10101010 */
|
||||||
else if (view & CANLIB_VIEW_ASCII) {
|
for (i = 0; i < cf->can_dlc; i++) {
|
||||||
j = dlen*(8-cf->can_dlc)+4;
|
buf[offset++] = ' ';
|
||||||
sprintf(buf+offset, "%*s", j, "'");
|
for (j = 7; j >= 0; j--)
|
||||||
offset += j;
|
buf[offset++] = (1<<j & cf->data[i])?'1':'0';
|
||||||
|
}
|
||||||
|
buf[offset] = 0; /* terminate string */
|
||||||
|
} else {
|
||||||
|
dlen = 3; /* _AA */
|
||||||
|
for (i = 0; i < cf->can_dlc; i++) {
|
||||||
|
sprintf(buf+offset, " %02X", cf->data[i]);
|
||||||
|
offset += dlen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < cf->can_dlc; i++)
|
if (cf->can_id & CAN_ERR_FLAG)
|
||||||
if ((cf->data[i] > 0x1F) && (cf->data[i] < 0x7F))
|
sprintf(buf+offset, "%*s", dlen*(8-cf->can_dlc)+13, "ERRORFRAME");
|
||||||
buf[offset++] = cf->data[i];
|
else if (view & CANLIB_VIEW_ASCII) {
|
||||||
else
|
j = dlen*(8-cf->can_dlc)+4;
|
||||||
buf[offset++] = '.';
|
sprintf(buf+offset, "%*s", j, "'");
|
||||||
|
offset += j;
|
||||||
|
|
||||||
sprintf(buf+offset, "'");
|
for (i = 0; i < cf->can_dlc; i++)
|
||||||
}
|
if ((cf->data[i] > 0x1F) && (cf->data[i] < 0x7F))
|
||||||
|
buf[offset++] = cf->data[i];
|
||||||
|
else
|
||||||
|
buf[offset++] = '.';
|
||||||
|
|
||||||
|
sprintf(buf+offset, "'");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
224
log2asc.c
224
log2asc.c
|
|
@ -60,129 +60,129 @@ extern int optind, opterr, optopt;
|
||||||
|
|
||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: %s [can-interfaces]\n", prg);
|
fprintf(stderr, "Usage: %s [can-interfaces]\n", prg);
|
||||||
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
|
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
|
||||||
fprintf(stderr, " -O <outfile> (default stdout)\n");
|
fprintf(stderr, " -O <outfile> (default stdout)\n");
|
||||||
fprintf(stderr, " -4 (reduce decimal place to 4 digits)\n");
|
fprintf(stderr, " -4 (reduce decimal place to 4 digits)\n");
|
||||||
fprintf(stderr, " -n (set newline to cr/lf - default lf)\n");
|
fprintf(stderr, " -n (set newline to cr/lf - default lf)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char buf[100], device[100], ascframe[100], id[10];
|
char buf[100], device[100], ascframe[100], id[10];
|
||||||
|
|
||||||
struct can_frame cf;
|
struct can_frame cf;
|
||||||
static struct timeval tv, start_tv;
|
static struct timeval tv, start_tv;
|
||||||
FILE *infile = stdin;
|
FILE *infile = stdin;
|
||||||
FILE *outfile = stdout;
|
FILE *outfile = stdout;
|
||||||
static int maxdev, devno, i, crlf, d4, opt;
|
static int maxdev, devno, i, crlf, d4, opt;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "I:O:4n")) != -1) {
|
while ((opt = getopt(argc, argv, "I:O:4n")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'I':
|
case 'I':
|
||||||
infile = fopen(optarg, "r");
|
infile = fopen(optarg, "r");
|
||||||
if (!infile) {
|
if (!infile) {
|
||||||
perror("infile");
|
perror("infile");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'O':
|
case 'O':
|
||||||
outfile = fopen(optarg, "w");
|
outfile = fopen(optarg, "w");
|
||||||
if (!outfile) {
|
if (!outfile) {
|
||||||
perror("outfile");
|
perror("outfile");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'n':
|
case 'n':
|
||||||
crlf = 1;
|
crlf = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '4':
|
case '4':
|
||||||
d4 = 1;
|
d4 = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Unknown option %c\n", opt);
|
fprintf(stderr, "Unknown option %c\n", opt);
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
maxdev = argc - optind; /* find real number of CAN devices */
|
|
||||||
|
|
||||||
if (!maxdev) {
|
|
||||||
fprintf(stderr, "no CAN interfaces defined!\n");
|
|
||||||
print_usage(basename(argv[0]));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//printf("Found %d CAN devices!\n", maxdev);
|
|
||||||
|
|
||||||
while (fgets(buf, 99, infile)) {
|
|
||||||
if (sscanf(buf, "(%ld.%ld) %s %s", &tv.tv_sec, &tv.tv_usec,
|
|
||||||
device, ascframe) != 4)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (!start_tv.tv_sec) { /* print banner */
|
|
||||||
start_tv = tv;
|
|
||||||
fprintf(outfile, "date %s", ctime(&start_tv.tv_sec));
|
|
||||||
fprintf(outfile, "base hex timestamps absolute%s",
|
|
||||||
(crlf)?"\r\n":"\n");
|
|
||||||
fprintf(outfile, "no internal events logged%s",
|
|
||||||
(crlf)?"\r\n":"\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0, devno=0; i<maxdev; i++) {
|
|
||||||
if (!strcmp(device, argv[optind+i])) {
|
|
||||||
devno = i+1; /* start with channel '1' */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (devno) { /* only convert for selected CAN devices */
|
|
||||||
if (parse_canframe(ascframe, &cf))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
tv.tv_sec = tv.tv_sec - start_tv.tv_sec;
|
|
||||||
tv.tv_usec = tv.tv_usec - start_tv.tv_usec;
|
|
||||||
if (tv.tv_usec < 0)
|
|
||||||
tv.tv_sec--, tv.tv_usec += 1000000;
|
|
||||||
if (tv.tv_sec < 0)
|
|
||||||
tv.tv_sec = tv.tv_usec = 0;
|
|
||||||
|
|
||||||
if (d4)
|
|
||||||
fprintf(outfile, "%4ld.%04ld ", tv.tv_sec, tv.tv_usec/100);
|
|
||||||
else
|
|
||||||
fprintf(outfile, "%4ld.%06ld ", tv.tv_sec, tv.tv_usec);
|
|
||||||
|
|
||||||
fprintf(outfile, "%-2d ", devno); /* channel number left aligned */
|
|
||||||
|
|
||||||
if (cf.can_id & CAN_ERR_FLAG)
|
|
||||||
fprintf(outfile, "ErrorFrame");
|
|
||||||
else {
|
|
||||||
sprintf(id, "%X%c", cf.can_id & CAN_EFF_MASK,
|
|
||||||
(cf.can_id & CAN_EFF_FLAG)?'x':' ');
|
|
||||||
fprintf(outfile, "%-15s Rx ", id);
|
|
||||||
|
|
||||||
if (cf.can_id & CAN_RTR_FLAG)
|
|
||||||
fprintf(outfile, "r"); /* RTR frame */
|
|
||||||
else {
|
|
||||||
fprintf(outfile, "d %d", cf.can_dlc); /* data frame */
|
|
||||||
|
|
||||||
for (i = 0; i < cf.can_dlc; i++) {
|
|
||||||
fprintf(outfile, " %02X", cf.data[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (crlf)
|
|
||||||
fprintf(outfile, "\r");
|
|
||||||
fprintf(outfile, "\n");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
fflush(outfile);
|
|
||||||
|
|
||||||
return 0;
|
maxdev = argc - optind; /* find real number of CAN devices */
|
||||||
|
|
||||||
|
if (!maxdev) {
|
||||||
|
fprintf(stderr, "no CAN interfaces defined!\n");
|
||||||
|
print_usage(basename(argv[0]));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("Found %d CAN devices!\n", maxdev);
|
||||||
|
|
||||||
|
while (fgets(buf, 99, infile)) {
|
||||||
|
if (sscanf(buf, "(%ld.%ld) %s %s", &tv.tv_sec, &tv.tv_usec,
|
||||||
|
device, ascframe) != 4)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!start_tv.tv_sec) { /* print banner */
|
||||||
|
start_tv = tv;
|
||||||
|
fprintf(outfile, "date %s", ctime(&start_tv.tv_sec));
|
||||||
|
fprintf(outfile, "base hex timestamps absolute%s",
|
||||||
|
(crlf)?"\r\n":"\n");
|
||||||
|
fprintf(outfile, "no internal events logged%s",
|
||||||
|
(crlf)?"\r\n":"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0, devno=0; i<maxdev; i++) {
|
||||||
|
if (!strcmp(device, argv[optind+i])) {
|
||||||
|
devno = i+1; /* start with channel '1' */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (devno) { /* only convert for selected CAN devices */
|
||||||
|
if (parse_canframe(ascframe, &cf))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
tv.tv_sec = tv.tv_sec - start_tv.tv_sec;
|
||||||
|
tv.tv_usec = tv.tv_usec - start_tv.tv_usec;
|
||||||
|
if (tv.tv_usec < 0)
|
||||||
|
tv.tv_sec--, tv.tv_usec += 1000000;
|
||||||
|
if (tv.tv_sec < 0)
|
||||||
|
tv.tv_sec = tv.tv_usec = 0;
|
||||||
|
|
||||||
|
if (d4)
|
||||||
|
fprintf(outfile, "%4ld.%04ld ", tv.tv_sec, tv.tv_usec/100);
|
||||||
|
else
|
||||||
|
fprintf(outfile, "%4ld.%06ld ", tv.tv_sec, tv.tv_usec);
|
||||||
|
|
||||||
|
fprintf(outfile, "%-2d ", devno); /* channel number left aligned */
|
||||||
|
|
||||||
|
if (cf.can_id & CAN_ERR_FLAG)
|
||||||
|
fprintf(outfile, "ErrorFrame");
|
||||||
|
else {
|
||||||
|
sprintf(id, "%X%c", cf.can_id & CAN_EFF_MASK,
|
||||||
|
(cf.can_id & CAN_EFF_FLAG)?'x':' ');
|
||||||
|
fprintf(outfile, "%-15s Rx ", id);
|
||||||
|
|
||||||
|
if (cf.can_id & CAN_RTR_FLAG)
|
||||||
|
fprintf(outfile, "r"); /* RTR frame */
|
||||||
|
else {
|
||||||
|
fprintf(outfile, "d %d", cf.can_dlc); /* data frame */
|
||||||
|
|
||||||
|
for (i = 0; i < cf.can_dlc; i++) {
|
||||||
|
fprintf(outfile, " %02X", cf.data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (crlf)
|
||||||
|
fprintf(outfile, "\r");
|
||||||
|
fprintf(outfile, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fflush(outfile);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
22
log2long.c
22
log2long.c
|
|
@ -54,17 +54,17 @@
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char buf[100], timestamp[100], device[100], ascframe[100];
|
char buf[100], timestamp[100], device[100], ascframe[100];
|
||||||
struct can_frame cf;
|
struct can_frame cf;
|
||||||
|
|
||||||
while (fgets(buf, 99, stdin)) {
|
while (fgets(buf, 99, stdin)) {
|
||||||
if (sscanf(buf, "%s %s %s", timestamp, device, ascframe) != 3)
|
if (sscanf(buf, "%s %s %s", timestamp, device, ascframe) != 3)
|
||||||
return 1;
|
return 1;
|
||||||
if (parse_canframe(ascframe, &cf))
|
if (parse_canframe(ascframe, &cf))
|
||||||
return 1;
|
return 1;
|
||||||
sprint_long_canframe(ascframe, &cf, 1); /* with ASCII output */
|
sprint_long_canframe(ascframe, &cf, 1); /* with ASCII output */
|
||||||
printf("%s %s %s\n", timestamp, device, ascframe);
|
printf("%s %s %s\n", timestamp, device, ascframe);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
154
vcan.c
154
vcan.c
|
|
@ -33,15 +33,15 @@
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
IFLA_INFO_UNSPEC,
|
IFLA_INFO_UNSPEC,
|
||||||
IFLA_INFO_NAME,
|
IFLA_INFO_NAME,
|
||||||
IFLA_INFO_DATA,
|
IFLA_INFO_DATA,
|
||||||
IFLA_INFO_XSTATS,
|
IFLA_INFO_XSTATS,
|
||||||
__IFLA_INFO_MAX,
|
__IFLA_INFO_MAX,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define NLMSG_TAIL(nmsg) \
|
#define NLMSG_TAIL(nmsg) \
|
||||||
((struct rtattr *)(((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
|
((struct rtattr *)(((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
|
||||||
|
|
||||||
int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
|
int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
|
||||||
|
|
@ -49,101 +49,101 @@ int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
|
||||||
|
|
||||||
void usage()
|
void usage()
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: vcan create\n"
|
fprintf(stderr, "Usage: vcan create\n"
|
||||||
" vcan delete iface\n");
|
" vcan delete iface\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
char *cmd, *dev;
|
char *cmd, *dev;
|
||||||
struct {
|
struct {
|
||||||
struct nlmsghdr n;
|
struct nlmsghdr n;
|
||||||
struct ifinfomsg i;
|
struct ifinfomsg i;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
} req;
|
} req;
|
||||||
struct sockaddr_nl nladdr;
|
struct sockaddr_nl nladdr;
|
||||||
struct rtattr *linkinfo;
|
struct rtattr *linkinfo;
|
||||||
|
|
||||||
#ifdef OBSOLETE
|
#ifdef OBSOLETE
|
||||||
fprintf(stderr, "This program is a temporary hack and is now obsolete.\n"
|
fprintf(stderr, "This program is a temporary hack and is now obsolete.\n"
|
||||||
"Please use ip(8) instead, i.e.\n"
|
"Please use ip(8) instead, i.e.\n"
|
||||||
" ip link add type vcan or\n"
|
" ip link add type vcan or\n"
|
||||||
" ip link delete iface\n");
|
" ip link delete iface\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
#endif
|
#endif
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
usage();
|
usage();
|
||||||
cmd = argv[1];
|
cmd = argv[1];
|
||||||
|
|
||||||
s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||||
|
|
||||||
memset(&req, 0, sizeof(req));
|
memset(&req, 0, sizeof(req));
|
||||||
|
|
||||||
if (strcmp(cmd, "create") == 0) {
|
if (strcmp(cmd, "create") == 0) {
|
||||||
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
||||||
req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
|
req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
|
||||||
req.n.nlmsg_type = RTM_NEWLINK;
|
req.n.nlmsg_type = RTM_NEWLINK;
|
||||||
req.n.nlmsg_seq = 0;
|
req.n.nlmsg_seq = 0;
|
||||||
req.i.ifi_family = AF_UNSPEC;
|
req.i.ifi_family = AF_UNSPEC;
|
||||||
|
|
||||||
linkinfo = NLMSG_TAIL(&req.n);
|
linkinfo = NLMSG_TAIL(&req.n);
|
||||||
addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
|
addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
|
||||||
addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, "vcan", strlen("vcan"));
|
addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, "vcan", strlen("vcan"));
|
||||||
linkinfo->rta_len = (void*)NLMSG_TAIL(&req.n) - (void*)linkinfo;
|
linkinfo->rta_len = (void*)NLMSG_TAIL(&req.n) - (void*)linkinfo;
|
||||||
|
|
||||||
} else if (strcmp(cmd, "delete") == 0) {
|
} else if (strcmp(cmd, "delete") == 0) {
|
||||||
if (argc < 3)
|
if (argc < 3)
|
||||||
usage();
|
usage();
|
||||||
dev = argv[2];
|
dev = argv[2];
|
||||||
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
||||||
req.n.nlmsg_flags = NLM_F_REQUEST;
|
req.n.nlmsg_flags = NLM_F_REQUEST;
|
||||||
req.n.nlmsg_type = RTM_DELLINK;
|
req.n.nlmsg_type = RTM_DELLINK;
|
||||||
req.i.ifi_family = AF_UNSPEC;
|
req.i.ifi_family = AF_UNSPEC;
|
||||||
req.i.ifi_index = if_nametoindex(dev);
|
req.i.ifi_index = if_nametoindex(dev);
|
||||||
} else
|
} else
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
memset(&nladdr, 0, sizeof(nladdr));
|
memset(&nladdr, 0, sizeof(nladdr));
|
||||||
nladdr.nl_family = AF_NETLINK;
|
nladdr.nl_family = AF_NETLINK;
|
||||||
nladdr.nl_pid = 0;
|
nladdr.nl_pid = 0;
|
||||||
nladdr.nl_groups = 0;
|
nladdr.nl_groups = 0;
|
||||||
#if 1
|
#if 1
|
||||||
sendto(s, &req, req.n.nlmsg_len, 0,
|
sendto(s, &req, req.n.nlmsg_len, 0,
|
||||||
(struct sockaddr*)&nladdr, sizeof(nladdr));
|
(struct sockaddr*)&nladdr, sizeof(nladdr));
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < req.n.nlmsg_len; i++) {
|
for (i = 0; i < req.n.nlmsg_len; i++) {
|
||||||
printf(" %02x", ((unsigned char*)&req)[i]);
|
printf(" %02x", ((unsigned char*)&req)[i]);
|
||||||
if (i % 16 == 15)
|
if (i % 16 == 15)
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
}
|
}
|
||||||
putchar('\n');
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
close(s);
|
close(s);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
|
int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
|
||||||
int alen)
|
int alen)
|
||||||
{
|
{
|
||||||
int len = RTA_LENGTH(alen);
|
int len = RTA_LENGTH(alen);
|
||||||
struct rtattr *rta;
|
struct rtattr *rta;
|
||||||
|
|
||||||
if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
|
if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
|
||||||
fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n",
|
fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n",
|
||||||
maxlen);
|
maxlen);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
rta = NLMSG_TAIL(n);
|
rta = NLMSG_TAIL(n);
|
||||||
rta->rta_type = type;
|
rta->rta_type = type;
|
||||||
rta->rta_len = len;
|
rta->rta_len = len;
|
||||||
memcpy(RTA_DATA(rta), data, alen);
|
memcpy(RTA_DATA(rta), data, alen);
|
||||||
n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
|
n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue