Merge branch 'master' into cansequence

pull/196/head
Ahmad Fatoum 2020-07-20 18:52:39 +02:00 committed by GitHub
commit 5d8248096e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 1401 additions and 809 deletions

8
.gitignore vendored
View File

@ -41,10 +41,10 @@ GNUmakefile.in
/isotpserver /isotpserver
/isotpsniffer /isotpsniffer
/isotptun /isotptun
/jacd /j1939acd
/jcat /j1939cat
/jspy /j1939spy
/jsr /j1939sr
/log2asc /log2asc
/log2long /log2long
/slcan_attach /slcan_attach

View File

@ -1,6 +1,7 @@
LOCAL_PATH := $(call my-dir) LOCAL_PATH := $(call my-dir)
PRIVATE_LOCAL_CFLAGS := -O2 -g -W -Wall \ PRIVATE_LOCAL_CFLAGS := -O2 -g -W -Wall \
-Wno-error=unused-parameter \
-DSO_RXQ_OVFL=40 \ -DSO_RXQ_OVFL=40 \
-DPF_CAN=29 \ -DPF_CAN=29 \
-DAF_CAN=PF_CAN -DAF_CAN=PF_CAN
@ -15,9 +16,104 @@ LOCAL_SRC_FILES := lib.c canframelen.c
LOCAL_MODULE := libcan LOCAL_MODULE := libcan
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_STATIC_LIBRARY) include $(BUILD_STATIC_LIBRARY)
#
# j1939lib
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := libj1939.c
LOCAL_MODULE := libj1939
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_STATIC_LIBRARY)
#
# j1939acd
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := j1939acd.c
LOCAL_MODULE := j1939acd
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libj1939
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
#
# j1939cat
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := j1939cat.c
LOCAL_MODULE := j1939cat
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libj1939
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
#
# j1939spy
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := j1939spy.c
LOCAL_MODULE := j1939spy
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libj1939
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
#
# j1939sr
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := j1939sr.c
LOCAL_MODULE := j1939sr
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libj1939
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
#
# testj1939
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := testj1939.c
LOCAL_MODULE := testj1939
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libj1939
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
# #
# candump # candump
# #
@ -30,6 +126,7 @@ LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libcan LOCAL_STATIC_LIBRARIES := libcan
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
@ -45,6 +142,7 @@ LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libcan LOCAL_STATIC_LIBRARIES := libcan
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
@ -74,10 +172,10 @@ LOCAL_MODULE := bcmserver
LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
# #
# can-calc-bit-timing # can-calc-bit-timing
# #
@ -89,6 +187,7 @@ LOCAL_MODULE := can-calc-bit-timing
LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
@ -104,6 +203,7 @@ LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libcan LOCAL_STATIC_LIBRARIES := libcan
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
@ -118,6 +218,7 @@ LOCAL_MODULE := canfdtest
LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
@ -133,6 +234,7 @@ LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libcan LOCAL_STATIC_LIBRARIES := libcan
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
@ -147,6 +249,7 @@ LOCAL_MODULE := cangw
LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
@ -162,6 +265,7 @@ LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libcan LOCAL_STATIC_LIBRARIES := libcan
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
@ -177,6 +281,7 @@ LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libcan LOCAL_STATIC_LIBRARIES := libcan
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
@ -191,6 +296,7 @@ LOCAL_MODULE := cansniffer
LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
@ -205,6 +311,7 @@ LOCAL_MODULE := isotpdump
LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
@ -219,6 +326,7 @@ LOCAL_MODULE := isotprecv
LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
@ -233,6 +341,7 @@ LOCAL_MODULE := isotpsend
LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
@ -247,6 +356,7 @@ LOCAL_MODULE := isotpserver
LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
@ -257,10 +367,11 @@ include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS) include $(CLEAR_VARS)
LOCAL_SRC_FILES := isotpsniffer.c LOCAL_SRC_FILES := isotpsniffer.c
LOCAL_MODULE := isotpsniffer.c LOCAL_MODULE := isotpsniffer
LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
@ -275,6 +386,7 @@ LOCAL_MODULE := isotptun
LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
@ -289,6 +401,7 @@ LOCAL_MODULE := isotpperf
LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
@ -304,6 +417,23 @@ LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libcan LOCAL_STATIC_LIBRARIES := libcan
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
#
# asc2log
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := asc2log.c
LOCAL_MODULE := asc2log
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libcan
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
@ -319,6 +449,7 @@ LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libcan LOCAL_STATIC_LIBRARIES := libcan
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
@ -333,6 +464,7 @@ LOCAL_MODULE := slcan_attach
LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
@ -347,6 +479,7 @@ LOCAL_MODULE := slcand
LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
@ -361,5 +494,6 @@ LOCAL_MODULE := slcanpty
LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)

View File

@ -37,10 +37,10 @@ set(PROGRAMS_CANLIB
) )
set(PROGRAMS_J1939 set(PROGRAMS_J1939
jacd j1939acd
jcat j1939cat
jspy j1939spy
jsr j1939sr
testj1939 testj1939
) )

View File

@ -59,10 +59,10 @@ bin_PROGRAMS = \
isotpserver \ isotpserver \
isotpsniffer \ isotpsniffer \
isotptun \ isotptun \
jacd \ j1939acd \
jcat \ j1939cat \
jspy \ j1939spy \
jsr \ j1939sr \
log2asc \ log2asc \
log2long \ log2long \
slcan_attach \ slcan_attach \
@ -70,10 +70,10 @@ bin_PROGRAMS = \
slcanpty \ slcanpty \
testj1939 testj1939
jacd_LDADD = libj1939.la j1939acd_LDADD = libj1939.la
jcat_LDADD = libj1939.la j1939cat_LDADD = libj1939.la
jspy_LDADD = libj1939.la j1939spy_LDADD = libj1939.la
jsr_LDADD = libj1939.la j1939sr_LDADD = libj1939.la
testj1939_LDADD = libj1939.la testj1939_LDADD = libj1939.la
EXTRA_DIST = \ EXTRA_DIST = \

View File

@ -67,10 +67,10 @@ PROGRAMS_ISOTP := \
isotptun isotptun
PROGRAMS_J1939 := \ PROGRAMS_J1939 := \
jacd \ j1939acd \
jcat \ j1939cat \
jspy \ j1939spy \
jsr \ j1939sr \
testj1939 testj1939
PROGRAMS_SLCAN := \ PROGRAMS_SLCAN := \
@ -120,10 +120,10 @@ canplayer.o: lib.h
cansend.o: lib.h cansend.o: lib.h
log2asc.o: lib.h log2asc.o: lib.h
log2long.o: lib.h log2long.o: lib.h
jacd.o: libj1939.h j1939acd.o: libj1939.h
jcat.o: libj1939.h j1939cat.o: libj1939.h
jspy.o: libj1939.h j1939spy.o: libj1939.h
jsr.o: libj1939.h j1939sr.o: libj1939.h
testj1939.o: libj1939.h testj1939.o: libj1939.h
canframelen.o: canframelen.h canframelen.o: canframelen.h
@ -136,9 +136,9 @@ canplayer: canplayer.o lib.o
cansend: cansend.o lib.o cansend: cansend.o lib.o
log2asc: log2asc.o lib.o log2asc: log2asc.o lib.o
log2long: log2long.o lib.o log2long: log2long.o lib.o
jacd: jacd.o libj1939.o j1939acd: j1939acd.o libj1939.o
jcat: jcat.o libj1939.o j1939cat: j1939cat.o libj1939.o
jspy: jspy.o libj1939.o j1939spy: j1939spy.o libj1939.o
jsr: jsr.o libj1939.o j1939sr: j1939sr.o libj1939.o
testj1939: testj1939.o libj1939.o testj1939: testj1939.o libj1939.o
canbusload: canbusload.o canframelen.o canbusload: canbusload.o canframelen.o

View File

@ -14,7 +14,7 @@ subsystem (aka SocketCAN):
* cansend : send a single frame * cansend : send a single frame
* cangen : generate (random) CAN traffic * cangen : generate (random) CAN traffic
* cansequence : send and check sequence of CAN frames with incrementing payload * cansequence : send and check sequence of CAN frames with incrementing payload
* cansniffer : display CAN data content differences (just 11bit CAN IDs) * cansniffer : display CAN data content differences
#### CAN access via IP sockets #### CAN access via IP sockets
* canlogserver : log CAN frames from a remote/local host * canlogserver : log CAN frames from a remote/local host

330
asc2log.c
View File

@ -57,16 +57,20 @@
#include "lib.h" #include "lib.h"
#define BUFLEN 400 /* CAN FD mode lines can be pretty long */
extern int optind, opterr, optopt; extern int optind, opterr, optopt;
void print_usage(char *prg) void print_usage(char *prg)
{ {
fprintf(stderr, "%s - convert ASC logfile to compact CAN frame logfile.\n", prg);
fprintf(stderr, "Usage: %s\n", prg); fprintf(stderr, "Usage: %s\n", prg);
fprintf(stderr, "Options: -I <infile> (default stdin)\n"); fprintf(stderr, "Options:\n");
fprintf(stderr, " -O <outfile> (default stdout)\n"); fprintf(stderr, "\t-I <infile>\t(default stdin)\n");
fprintf(stderr, "\t-O <outfile>\t(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 canfd_frame *cf, unsigned int max_dlen) {
fprintf(file, "(%ld.%06ld) ", tv->tv_sec, tv->tv_usec); fprintf(file, "(%ld.%06ld) ", tv->tv_sec, tv->tv_usec);
@ -75,11 +79,10 @@ void prframe(FILE *file, struct timeval *tv, int dev, struct can_frame *cf) {
else else
fprintf(file, "canX "); fprintf(file, "canX ");
/* no CAN FD support so far */ fprint_canframe(file, cf, "\n", 0, max_dlen);
fprint_canframe(file, (struct canfd_frame *)cf, "\n", 0, CAN_MAX_DLEN);
} }
void get_can_id(struct can_frame *cf, char *idstring, int base) { void get_can_id(struct canfd_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;
@ -122,14 +125,207 @@ void calc_tv(struct timeval *tv, struct timeval *read_tv,
} }
} }
void eval_can(char* buf, struct timeval *date_tvp, char timestamps, char base, int dplace, FILE *outfile) {
int interface;
static struct timeval tv; /* current frame timestamp */
static struct timeval read_tv; /* frame timestamp from ASC file */
struct canfd_frame cf;
char rtr;
int dlc = 0;
int data[8];
char tmp1[BUFLEN];
int i, items, found;
/* 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 */
items = 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]);
if ((items == dlc + 6 ) || /* data frame */
((items == 5) && (rtr == 'r')) || /* RTR without DLC */
((items == 6) && (rtr == 'r'))) { /* RTR with DLC */
found = 1;
get_can_id(&cf, tmp1, 16);
}
} else { /* check for CAN frames with decimal values */
items = 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]);
if ((items == dlc + 6 ) || /* data frame */
((items == 5) && (rtr == 'r')) || /* RTR without DLC */
((items == 6) && (rtr == 'r'))) { /* RTR with DLC */
found = 1;
get_can_id(&cf, tmp1, 10);
}
}
if (found) {
if (dlc > CAN_MAX_DLC)
return;
cf.len = dlc;
if (rtr == 'r')
cf.can_id |= CAN_RTR_FLAG;
else
for (i = 0; i < dlc; i++)
cf.data[i] = data[i] & 0xFFU;
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
prframe(outfile, &tv, interface, &cf, CAN_MAX_DLEN);
fflush(outfile);
return;
}
/* check for ErrorFrames */
if (sscanf(buf, "%ld.%ld %d %s",
&read_tv.tv_sec, &read_tv.tv_usec,
&interface, tmp1) == 4) {
if (!strncmp(tmp1, "ErrorFrame", strlen("ErrorFrame"))) {
memset(&cf, 0, sizeof(cf));
/* do not know more than 'Error' */
cf.can_id = (CAN_ERR_FLAG | CAN_ERR_BUSERROR);
cf.len = CAN_ERR_DLC;
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
prframe(outfile, &tv, interface, &cf, CAN_MAX_DLEN);
fflush(outfile);
}
}
}
void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps, int dplace, FILE *outfile) {
int interface;
static struct timeval tv; /* current frame timestamp */
static struct timeval read_tv; /* frame timestamp from ASC file */
struct canfd_frame cf;
unsigned char brs, esi, ctmp;
unsigned int flags;
int dlc, dlen = 0;
char tmp1[BUFLEN];
char *ptr;
int i;
/* The CANFD format is mainly in hex representation but <DataLength>
and probably some content we skip anyway. Don't trust the docs! */
/* 21.671796 CANFD 1 Tx 11 msgCanFdFr1 1 0 a 16 \
00 00 00 00 00 00 00 00 00 00 00 00 00 00 59 c0 \
100000 214 223040 80000000 46500250 460a0250 20011736 20010205 */
memset(&cf, 0, sizeof(cf));
/* check for valid line without symbolic name */
if (sscanf(buf, "%ld.%ld %*s %d %*s %s %hhx %hhx %x %d ",
&read_tv.tv_sec, &read_tv.tv_usec, &interface,
tmp1, &brs, &esi, &dlc, &dlen) != 8) {
/* check for valid line with a symbolic name */
if (sscanf(buf, "%ld.%ld %*s %d %*s %s %*s %hhx %hhx %x %d ",
&read_tv.tv_sec, &read_tv.tv_usec, &interface,
tmp1, &brs, &esi, &dlc, &dlen) != 8) {
/* no valid CANFD format pattern */
return;
}
}
/* check for allowed (unsigned) value ranges */
if ((dlen > CANFD_MAX_DLEN) || (dlc > CANFD_MAX_DLC) ||
(brs > 1) || (esi > 1))
return;
/* don't trust ASCII content - sanitize data length */
if (dlen != can_dlc2len(can_len2dlc(dlen)))
return;
get_can_id(&cf, tmp1, 16);
/* now search for the beginning of the data[] content */
sprintf(tmp1, " %x %x %x %2d ", brs, esi, dlc, dlen);
/* search for the pattern generated by real data */
ptr = strcasestr(buf, tmp1);
if (ptr == NULL)
return;
ptr += strlen(tmp1); /* start of ASCII hex frame data */
cf.len = dlen;
for (i = 0; i < dlen; i++) {
ctmp = asc2nibble(ptr[0]);
if (ctmp > 0x0F)
return;
cf.data[i] = (ctmp << 4);
ctmp = asc2nibble(ptr[1]);
if (ctmp > 0x0F)
return;
cf.data[i] |= ctmp;
ptr += 3; /* start of next ASCII hex byte */
}
/* skip MessageDuration and MessageLength to get Flags value */
if (sscanf(ptr, " %*x %*x %x ", &flags) != 1)
return;
/* relevant flags in Flags field */
#define ASC_F_RTR 0x00000010
#define ASC_F_FDF 0x00001000
#define ASC_F_BRS 0x00002000
#define ASC_F_ESI 0x00004000
if (flags & ASC_F_FDF) {
dlen = CANFD_MAX_DLEN;
if (flags & ASC_F_BRS)
cf.flags |= CANFD_BRS;
if (flags & ASC_F_ESI)
cf.flags |= CANFD_ESI;
} else {
/* yes. The 'CANFD' format supports classic CAN content! */
dlen = CAN_MAX_DLEN;
if (flags & ASC_F_RTR) {
cf.can_id |= CAN_RTR_FLAG;
/* dlen is always 0 for classic CAN RTR frames
but the DLC value is valid in RTR cases */
cf.len = dlc;
}
}
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
prframe(outfile, &tv, interface, &cf, dlen);
fflush(outfile);
return;
/* No support for really strange CANFD ErrorFrames format m( */
}
int get_date(struct timeval *tv, char *date) { int get_date(struct timeval *tv, char *date) {
char ctmp[10];
int itmp;
struct tm tms; struct tm tms;
unsigned int msecs = 0;
if (sscanf(date, "%9s %d %9s %9s %d", ctmp, &itmp, ctmp, ctmp, &itmp) == 5) { if (strcasestr(date, " pm ") != NULL) {
/* 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")) {
@ -137,29 +333,41 @@ int get_date(struct timeval *tv, char *date) {
return 1; return 1;
} }
if (!strptime(date, "%B %d %r %Y", &tms)) if (!strptime(date, "%B %d %I:%M:%S %p %Y", &tms)) {
return 1; /* The string might contain a milliseconds value which strptime()
does not support. So we read the ms value into the year variable
before parsing the real year value (hack) */
if (!strptime(date, "%B %d %I:%M:%S.%Y %p %Y", &tms))
return 1;
else
sscanf(date, "%*s %*d %*d:%*d:%*d.%3u ", &msecs);
}
} 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)
return 1;
if (!setlocale(LC_TIME, "de_DE")) { if (!setlocale(LC_TIME, "de_DE")) {
fprintf(stderr, "Setting locale to 'de_DE' failed!\n"); fprintf(stderr, "Setting locale to 'de_DE' failed!\n");
return 1; return 1;
} }
if (!strptime(date, "%B %d %T %Y", &tms)) if (!strptime(date, "%B %d %H:%M:%S %Y", &tms)) {
return 1; /* The string might contain a milliseconds value which strptime()
does not support. So we read the ms value into the year variable
before parsing the real year value (hack) */
if (!strptime(date, "%B %d %H:%M:%S.%Y %Y", &tms))
return 1;
else
sscanf(date, "%*s %*d %*d:%*d:%*d.%3u ", &msecs);
}
} }
//printf("h %d m %d s %d d %d m %d y %d\n", //printf("h %d m %d s %d ms %03d 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, msecs,
//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);
tv->tv_usec = msecs * 1000;
if (tv->tv_sec < 0) if (tv->tv_sec < 0)
return 1; return 1;
@ -169,24 +377,17 @@ int get_date(struct timeval *tv, char *date) {
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
char buf[100], tmp1[100], tmp2[100]; char buf[BUFLEN], tmp1[BUFLEN], tmp2[BUFLEN];
FILE *infile = stdin; FILE *infile = stdin;
FILE *outfile = stdout; FILE *outfile = stdout;
static int verbose; static int verbose;
struct can_frame cf; static struct timeval tmp_tv; /* tmp frame timestamp from ASC file */
static struct timeval tv; /* current frame timestamp */
static struct timeval read_tv; /* frame timestamp from ASC file */
static struct timeval date_tv; /* date of the ASC file */ static struct timeval date_tv; /* date of the ASC file */
static int dplace; /* decimal place 4, 5 or 6 or uninitialized */ static int dplace; /* decimal place 4, 5 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 opt;
int interface;
char rtr;
int dlc = 0;
int data[8];
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) {
@ -224,7 +425,7 @@ int main(int argc, char **argv)
} }
while (fgets(buf, 99, infile)) { while (fgets(buf, BUFLEN-1, infile)) {
if (!dplace) { /* the representation of a valid CAN frame not known */ if (!dplace) { /* the representation of a valid CAN frame not known */
@ -264,7 +465,7 @@ int main(int argc, char **argv)
} }
/* check for decimal places length in valid CAN frames */ /* check for decimal places length in valid CAN frames */
if (sscanf(buf, "%ld.%s %d ", &tv.tv_sec, tmp2, &i) == 3){ if (sscanf(buf, "%ld.%s %s ", &tmp_tv.tv_sec, tmp2, tmp1) == 3){
dplace = strlen(tmp2); dplace = strlen(tmp2);
if (verbose) if (verbose)
printf("decimal place %d, e.g. '%s'\n", dplace, tmp2); printf("decimal place %d, e.g. '%s'\n", dplace, tmp2);
@ -279,67 +480,12 @@ int main(int argc, char **argv)
/* the representation of a valid CAN frame is known here */ /* the representation of a valid CAN frame is known here */
/* so try to get CAN frames and ErrorFrames and convert them */ /* 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 */ /* check classic CAN format or the CANFD tag which can take both types */
if (sscanf(buf, "%ld.%ld %s ", &tmp_tv.tv_sec, &tmp_tv.tv_usec, tmp1) == 3){
found = 0; /* found valid CAN frame ? */ if (!strncmp(tmp1, "CANFD", 5))
eval_canfd(buf, &date_tv, timestamps, dplace, outfile);
if (base == 'h') { /* check for CAN frames with hexadecimal values */ else
eval_can(buf, &date_tv, timestamps, base, dplace, outfile);
if (sscanf(buf, "%ld.%ld %d %s %*s %c %d %x %x %x %x %x %x %x %x",
&read_tv.tv_sec, &read_tv.tv_usec, &interface,
tmp1, &rtr, &dlc,
&data[0], &data[1], &data[2], &data[3],
&data[4], &data[5], &data[6], &data[7]
) == dlc + 6 ) {
found = 1;
get_can_id(&cf, tmp1, 16);
}
} else { /* check for CAN frames with decimal values */
if (sscanf(buf, "%ld.%ld %d %s %*s %c %d %d %d %d %d %d %d %d %d",
&read_tv.tv_sec, &read_tv.tv_usec, &interface,
tmp1, &rtr, &dlc,
&data[0], &data[1], &data[2], &data[3],
&data[4], &data[5], &data[6], &data[7]
) == dlc + 6 ) {
found = 1;
get_can_id(&cf, tmp1, 10);
}
}
if (found) {
if (rtr == 'r')
cf.can_id |= CAN_RTR_FLAG;
cf.can_dlc = dlc & 0x0FU;
for (i=0; i<dlc; i++)
cf.data[i] = data[i] & 0xFFU;
calc_tv(&tv, &read_tv, &date_tv, timestamps, dplace);
prframe(outfile, &tv, interface, &cf);
fflush(outfile);
continue;
}
/* check for ErrorFrames */
if (sscanf(buf, "%ld.%ld %d %s",
&read_tv.tv_sec, &read_tv.tv_usec,
&interface, tmp1) == 4) {
if (!strncmp(tmp1, "ErrorFrame", strlen("ErrorFrame"))) {
memset(&cf, 0, sizeof(cf));
/* do not know more than 'Error' */
cf.can_id = (CAN_ERR_FLAG | CAN_ERR_BUSERROR);
cf.can_dlc = CAN_ERR_DLC;
calc_tv(&tv, &read_tv, &date_tv, timestamps, dplace);
prframe(outfile, &tv, interface, &cf);
fflush(outfile);
}
} }
} }
fclose(outfile); fclose(outfile);

View File

@ -135,7 +135,7 @@ void childdied(int i)
wait(NULL); wait(NULL);
} }
int main(int argc, char **argv) int main(void)
{ {
int sl, sa, sc; int sl, sa, sc;

View File

@ -23,6 +23,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <libgen.h>
#include <string.h> #include <string.h>
#include <linux/types.h> #include <linux/types.h>
@ -131,17 +132,16 @@ static inline void *netdev_priv(const struct net_device *dev)
static void print_usage(char *cmd) static void print_usage(char *cmd)
{ {
printf("%s - calculate CAN bit timing parameters.\n", cmd);
printf("Usage: %s [options] [<CAN-contoller-name>]\n" printf("Usage: %s [options] [<CAN-contoller-name>]\n"
"\tOptions:\n" "Options:\n"
"\t-q : don't print header line\n" "\t-q don't print header line\n"
"\t-l : list all support CAN controller names\n" "\t-l list all support CAN controller names\n"
"\t-b <bitrate> : bit-rate in bits/sec\n" "\t-b <bitrate> bit-rate in bits/sec\n"
"\t-s <samp_pt> : sample-point in one-tenth of a percent\n" "\t-s <samp_pt> sample-point in one-tenth of a percent\n"
"\t or 0 for CIA recommended sample points\n" "\t or 0 for CIA recommended sample points\n"
"\t-c <clock> : real CAN system clock in Hz\n", "\t-c <clock> real CAN system clock in Hz\n",
cmd); cmd);
exit(EXIT_FAILURE);
} }
static void printf_btr_sja1000(struct can_bittiming *bt, bool hdr) static void printf_btr_sja1000(struct can_bittiming *bt, bool hdr)
@ -638,7 +638,7 @@ int main(int argc, char *argv[])
const struct calc_bittiming_const *btc; const struct calc_bittiming_const *btc;
while ((opt = getopt(argc, argv, "b:c:lqs:")) != -1) { while ((opt = getopt(argc, argv, "b:c:lqs:?")) != -1) {
switch (opt) { switch (opt) {
case 'b': case 'b':
bitrate_nominal = atoi(optarg); bitrate_nominal = atoi(optarg);
@ -660,14 +660,22 @@ int main(int argc, char *argv[])
spt_nominal = strtoul(optarg, NULL, 10); spt_nominal = strtoul(optarg, NULL, 10);
break; break;
case '?':
print_usage(basename(argv[0]));
exit(EXIT_SUCCESS);
break;
default: default:
print_usage(argv[0]); print_usage(basename(argv[0]));
exit(EXIT_FAILURE);
break; break;
} }
} }
if (argc > optind + 1) if (argc > optind + 1) {
print_usage(argv[0]); print_usage(argv[0]);
exit(EXIT_FAILURE);
}
if (argc == optind + 1) if (argc == optind + 1)
name = argv[optind]; name = argv[optind];
@ -677,8 +685,10 @@ int main(int argc, char *argv[])
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
if (spt_nominal && (spt_nominal >= 1000 || spt_nominal < 100)) if (spt_nominal && (spt_nominal >= 1000 || spt_nominal < 100)) {
print_usage(argv[0]); print_usage(argv[0]);
exit(EXIT_FAILURE);
}
for (i = 0; i < ARRAY_SIZE(can_calc_consts); i++) { for (i = 0; i < ARRAY_SIZE(can_calc_consts); i++) {
if (name && strcmp(can_calc_consts[i].bittiming_const.name, name)) if (name && strcmp(can_calc_consts[i].bittiming_const.name, name))

View File

@ -44,7 +44,7 @@ You should have this output in terminal 1
40 02300: 01 23 40 02300: 01 23
This means, from NAME 0, SA 40, PGN 02300 was received, This means, from NAME 0, SA 40, PGN 02300 was received,
with 2 databytes, *01* & *02*. with 2 databytes, *01* & *23*.
now emit this CAN message: now emit this CAN message:

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/* /*
* canbusload.c * canbusload.c - monitor CAN bus load
* *
* Copyright (c) 2002-2008 Volkswagen Group Electronic Research * Copyright (c) 2002-2008 Volkswagen Group Electronic Research
* All rights reserved. * All rights reserved.
@ -91,14 +91,16 @@ static char *prg;
void print_usage(char *prg) void print_usage(char *prg)
{ {
fprintf(stderr, "%s - monitor CAN bus load.\n", 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:\n");
fprintf(stderr, " -c (colorize lines)\n"); fprintf(stderr, " -t (show current time on the first line)\n");
fprintf(stderr, " -b (show bargraph in %d%% resolution)\n", PERCENTRES); fprintf(stderr, " -c (colorize lines)\n");
fprintf(stderr, " -r (redraw the terminal - similar to top)\n"); fprintf(stderr, " -b (show bargraph in %d%% resolution)\n", PERCENTRES);
fprintf(stderr, " -i (ignore bitstuffing in bandwidth calculation)\n"); fprintf(stderr, " -r (redraw the terminal - similar to top)\n");
fprintf(stderr, " -e (exact calculation of stuffed bits)\n"); fprintf(stderr, " -i (ignore bitstuffing in bandwidth calculation)\n");
fprintf(stderr, " -e (exact calculation of stuffed bits)\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");
@ -107,7 +109,7 @@ void print_usage(char *prg)
fprintf(stderr, "Due to the bitstuffing estimation the calculated busload may exceed 100%%.\n"); fprintf(stderr, "Due to the bitstuffing estimation the calculated busload may exceed 100%%.\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, "\nExamples:\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 2014-02-01 21:13:16 (worst case bitstuffing)\n", prg); fprintf(stderr, "%s 2014-02-01 21:13:16 (worst case bitstuffing)\n", prg);
fprintf(stderr, " can0@100000 805 74491 36656 74%% |XXXXXXXXXXXXXX......|\n"); fprintf(stderr, " can0@100000 805 74491 36656 74%% |XXXXXXXXXXXXXX......|\n");
@ -298,7 +300,7 @@ int main(int argc, char **argv)
ptr = argv[optind+i]; ptr = argv[optind+i];
nbytes = strlen(ptr); nbytes = strlen(ptr);
if (nbytes >= IFNAMSIZ+sizeof("@1000000")+1) { if (nbytes >= (int)(IFNAMSIZ+sizeof("@1000000")+1)) {
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;
} }
@ -322,7 +324,7 @@ int main(int argc, char **argv)
nbytes = nptr - ptr; /* interface name is up the first '@' */ nbytes = nptr - ptr; /* interface name is up the first '@' */
if (nbytes >= IFNAMSIZ) { if (nbytes >= (int)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;
} }
@ -394,7 +396,7 @@ int main(int argc, char **argv)
return 1; return 1;
} }
if (nbytes < sizeof(struct can_frame)) { if (nbytes < (int)sizeof(struct can_frame)) {
fprintf(stderr, "read: incomplete CAN frame\n"); fprintf(stderr, "read: incomplete CAN frame\n");
return 1; return 1;
} }

View File

@ -116,9 +116,11 @@ static volatile int running = 1;
void print_usage(char *prg) void print_usage(char *prg)
{ {
fprintf(stderr, "%s - dump CAN bus traffic.\n", 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:\n");
fprintf(stderr, " -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n");
fprintf(stderr, " -H (read hardware timestamps instead of system timestamps)\n"); fprintf(stderr, " -H (read hardware timestamps instead of system timestamps)\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");
@ -137,22 +139,23 @@ void print_usage(char *prg)
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, "\nComma separated filters can be specified for each given CAN interface:\n"); fprintf(stderr, "\nFilters:\n");
fprintf(stderr, " <can_id>:<can_mask> (matches when <received_can_id> & mask == can_id & mask)\n"); fprintf(stderr, " Comma separated filters can be specified for each given CAN interface:\n");
fprintf(stderr, " <can_id>~<can_mask> (matches when <received_can_id> & mask != can_id & mask)\n"); fprintf(stderr, " <can_id>:<can_mask>\n (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, " <can_id>~<can_mask>\n (matches when <received_can_id> & mask != can_id & mask)\n");
fprintf(stderr, " [j|J] (join the given CAN filters - logical AND semantic)\n"); fprintf(stderr, " #<error_mask>\n (set error frame filter, see include/linux/can/error.h)\n");
fprintf(stderr, " [j|J]\n (join the given CAN filters - logical AND semantic)\n");
fprintf(stderr, "\nCAN IDs, masks and data content are given and expected in hexadecimal values.\n"); fprintf(stderr, "\nCAN IDs, masks and data content are given and expected in hexadecimal values.\n");
fprintf(stderr, "When the can_id is 8 digits long the CAN_EFF_FLAG is set for 29 bit EFF format.\n"); fprintf(stderr, "When the can_id is 8 digits long the CAN_EFF_FLAG is set for 29 bit EFF format.\n");
fprintf(stderr, "Without any given filter all data frames are received ('0:0' default filter).\n"); fprintf(stderr, "Without any given filter all data frames are received ('0:0' default filter).\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, "\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\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\n (log only error frames but no(!) data frames)\n", prg);
fprintf(stderr, "%s -l any,0:0,#FFFFFFFF (log error frames and also all data frames)\n", prg); fprintf(stderr, "%s -l any,0:0,#FFFFFFFF\n (log error frames and also all data frames)\n", prg);
fprintf(stderr, "%s vcan2,12345678:DFFFFFFF (match only for extended CAN ID 12345678)\n", prg); fprintf(stderr, "%s vcan2,12345678:DFFFFFFF\n (match only for extended CAN ID 12345678)\n", prg);
fprintf(stderr, "%s vcan2,123:7FF (matches CAN ID 123 - including EFF and RTR frames)\n", prg); fprintf(stderr, "%s vcan2,123:7FF\n (matches CAN ID 123 - including EFF and RTR frames)\n", prg);
fprintf(stderr, "%s vcan2,123:C00007FF (matches CAN ID 123 - only SFF and non-RTR frames)\n", prg); fprintf(stderr, "%s vcan2,123:C00007FF\n (matches CAN ID 123 - only SFF and non-RTR frames)\n", prg);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
@ -198,7 +201,7 @@ int idx2dindex(int ifidx, int socket) {
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0) if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
perror("SIOCGIFNAME"); perror("SIOCGIFNAME");
if (max_devname_len < strlen(ifr.ifr_name)) if (max_devname_len < (int)strlen(ifr.ifr_name))
max_devname_len = strlen(ifr.ifr_name); max_devname_len = strlen(ifr.ifr_name);
strcpy(devname[i], ifr.ifr_name); strcpy(devname[i], ifr.ifr_name);

View File

@ -28,6 +28,7 @@
#include <sched.h> #include <sched.h>
#include <limits.h> #include <limits.h>
#include <errno.h> #include <errno.h>
#include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/time.h> #include <sys/time.h>
@ -48,31 +49,37 @@ static int verbose;
static int sockfd; static int sockfd;
static int test_loops; static int test_loops;
static int exit_sig; static int exit_sig;
static int inflight_count = CAN_MSG_COUNT;
static void print_usage(char *prg) static void print_usage(char *prg)
{ {
fprintf(stderr, fprintf(stderr,
"%s - Full-duplex test program (DUT and host part).\n"
"Usage: %s [options] <can-interface>\n" "Usage: %s [options] <can-interface>\n"
"\n" "\n"
"Options: -v (low verbosity)\n" "Options:\n"
" -v (low verbosity)\n"
" -vv (high verbosity)\n" " -vv (high verbosity)\n"
" -g (generate messages)\n" " -g (generate messages)\n"
" -l COUNT (test loop count)\n" " -l COUNT (test loop count)\n"
" -f COUNT (number of frames in flight, default: %d)\n"
"\n" "\n"
"With the option '-g' CAN messages are generated and checked\n" "With the option '-g' CAN messages are generated and checked\n"
"on <can-interface>, otherwise all messages received on the\n" "on <can-interface>, otherwise all messages received on the\n"
"<can-interface> are sent back incrementing the CAN id and\n" "<can-interface> are sent back incrementing the CAN id and\n"
"all data bytes. The program can be aborted with ^C.\n" "all data bytes. The program can be aborted with ^C.\n"
"\n" "\n"
"Example:\n" "Examples:\n"
"\ton DUT : %s -v can0\n" "\ton DUT:\n"
"\ton Host: %s -g -v can2\n", "%s -v can0\n"
prg, prg, prg); "\ton Host:\n"
"%s -g -v can2\n",
prg, prg, CAN_MSG_COUNT, prg, prg);
exit(1); exit(1);
} }
static void print_frame(struct can_frame *frame, int inc) static void print_frame(const struct can_frame *frame, int inc)
{ {
int i; int i;
@ -82,12 +89,12 @@ static void print_frame(struct can_frame *frame, int inc)
} else { } else {
printf("[%d]", frame->can_dlc); printf("[%d]", frame->can_dlc);
for (i = 0; i < frame->can_dlc; i++) for (i = 0; i < frame->can_dlc; i++)
printf(" %02x", frame->data[i] + inc); printf(" %02x", (uint8_t)(frame->data[i] + inc));
} }
printf("\n"); printf("\n");
} }
static void print_compare(struct can_frame *exp, struct can_frame *rec, int inc) static void print_compare(const struct can_frame *exp, const struct can_frame *rec, int inc)
{ {
printf("expected: "); printf("expected: ");
print_frame(exp, inc); print_frame(exp, inc);
@ -109,8 +116,8 @@ static void compare_frame(struct can_frame *exp, struct can_frame *rec, int inc)
running = 0; running = 0;
} else { } else {
for (i = 0; i < rec->can_dlc; i++) { for (i = 0; i < rec->can_dlc; i++) {
if (rec->data[i] != ((exp->data[i] + inc) & 0xff)) { if (rec->data[i] != (uint8_t)(exp->data[i] + inc)) {
printf("Databyte %x mismatch !\n", i); printf("Databyte %x mismatch!\n", i);
print_compare(exp, print_compare(exp,
rec, inc); rec, inc);
running = 0; running = 0;
@ -192,11 +199,47 @@ static int send_frame(struct can_frame *frame)
return 0; return 0;
} }
static int check_frame(const struct can_frame *frame)
{
int err = 0;
int i;
if (frame->can_id != CAN_MSG_ID) {
printf("unexpected Message ID 0x%04x!\n", frame->can_id);
err = -1;
}
if (frame->can_dlc != CAN_MSG_LEN) {
printf("unexpected Message length %d!\n", frame->can_dlc);
err = -1;
}
for (i = 1; i < frame->can_dlc; i++) {
if (frame->data[i] != frame->data[i-1]) {
printf("Frame inconsistent!\n");
print_frame(frame, 0);
err = -1;
goto out;
}
}
out:
return err;
}
static void inc_frame(struct can_frame *frame)
{
int i;
frame->can_id++;
for (i = 0; i < frame->can_dlc; i++)
frame->data[i]++;
}
static int can_echo_dut(void) static int can_echo_dut(void)
{ {
unsigned int frame_count = 0; unsigned int frame_count = 0;
struct can_frame frame; struct can_frame frame;
int i;
while (running) { while (running) {
if (recv_frame(&frame)) if (recv_frame(&frame))
@ -205,19 +248,11 @@ static int can_echo_dut(void)
if (verbose == 1) { if (verbose == 1) {
echo_progress(frame.data[0]); echo_progress(frame.data[0]);
} else if (verbose > 1) { } else if (verbose > 1) {
printf("%04x: ", frame.can_id); print_frame(&frame, 0);
if (frame.can_id & CAN_RTR_FLAG) {
printf("remote request");
} else {
printf("[%d]", frame.can_dlc);
for (i = 0; i < frame.can_dlc; i++)
printf(" %02x", frame.data[i]);
}
printf("\n");
} }
frame.can_id++;
for (i = 0; i < frame.can_dlc; i++) check_frame(&frame);
frame.data[i]++; inc_frame(&frame);
if (send_frame(&frame)) if (send_frame(&frame))
return -1; return -1;
@ -236,15 +271,26 @@ static int can_echo_dut(void)
static int can_echo_gen(void) static int can_echo_gen(void)
{ {
struct can_frame tx_frames[CAN_MSG_COUNT]; struct can_frame *tx_frames;
int recv_tx[CAN_MSG_COUNT]; int *recv_tx;
struct can_frame rx_frame; struct can_frame rx_frame;
unsigned char counter = 0; unsigned char counter = 0;
int send_pos = 0, recv_rx_pos = 0, recv_tx_pos = 0, unprocessed = 0, loops = 0; int send_pos = 0, recv_rx_pos = 0, recv_tx_pos = 0, unprocessed = 0, loops = 0;
int err = 0;
int i; int i;
tx_frames = calloc(inflight_count, sizeof(* tx_frames));
if (!tx_frames)
return -1;
recv_tx = calloc(inflight_count, sizeof(* recv_tx));
if (!recv_tx) {
err = -1;
goto out_free_tx_frames;
}
while (running) { while (running) {
if (unprocessed < CAN_MSG_COUNT) { if (unprocessed < inflight_count) {
/* still send messages */ /* still send messages */
tx_frames[send_pos].can_dlc = CAN_MSG_LEN; tx_frames[send_pos].can_dlc = CAN_MSG_LEN;
tx_frames[send_pos].can_id = CAN_MSG_ID; tx_frames[send_pos].can_id = CAN_MSG_ID;
@ -252,11 +298,13 @@ static int can_echo_gen(void)
for (i = 0; i < CAN_MSG_LEN; i++) for (i = 0; i < CAN_MSG_LEN; i++)
tx_frames[send_pos].data[i] = counter + i; tx_frames[send_pos].data[i] = counter + i;
if (send_frame(&tx_frames[send_pos])) if (send_frame(&tx_frames[send_pos])) {
return -1; err = -1;
goto out_free;
}
send_pos++; send_pos++;
if (send_pos == CAN_MSG_COUNT) if (send_pos == inflight_count)
send_pos = 0; send_pos = 0;
unprocessed++; unprocessed++;
if (verbose == 1) if (verbose == 1)
@ -268,8 +316,10 @@ static int can_echo_gen(void)
else else
millisleep(1); millisleep(1);
} else { } else {
if (recv_frame(&rx_frame)) if (recv_frame(&rx_frame)) {
return -1; err = -1;
goto out_free;
}
if (verbose > 1) if (verbose > 1)
print_frame(&rx_frame, 0); print_frame(&rx_frame, 0);
@ -279,7 +329,7 @@ static int can_echo_gen(void)
compare_frame(&tx_frames[recv_tx_pos], &rx_frame, 0); compare_frame(&tx_frames[recv_tx_pos], &rx_frame, 0);
recv_tx[recv_tx_pos] = 1; recv_tx[recv_tx_pos] = 1;
recv_tx_pos++; recv_tx_pos++;
if (recv_tx_pos == CAN_MSG_COUNT) if (recv_tx_pos == inflight_count)
recv_tx_pos = 0; recv_tx_pos = 0;
continue; continue;
} else { } else {
@ -290,7 +340,7 @@ static int can_echo_gen(void)
/* compare with expected */ /* compare with expected */
compare_frame(&tx_frames[recv_rx_pos], &rx_frame, 1); compare_frame(&tx_frames[recv_rx_pos], &rx_frame, 1);
recv_rx_pos++; recv_rx_pos++;
if (recv_rx_pos == CAN_MSG_COUNT) if (recv_rx_pos == inflight_count)
recv_rx_pos = 0; recv_rx_pos = 0;
} }
@ -304,7 +354,12 @@ static int can_echo_gen(void)
printf("\nTest messages sent and received: %d\n", loops); printf("\nTest messages sent and received: %d\n", loops);
return 0; out_free:
free(recv_tx);
out_free_tx_frames:
free(tx_frames);
return err;
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@ -320,20 +375,24 @@ int main(int argc, char *argv[])
signal(SIGHUP, signal_handler); signal(SIGHUP, signal_handler);
signal(SIGINT, signal_handler); signal(SIGINT, signal_handler);
while ((opt = getopt(argc, argv, "gl:v")) != -1) { while ((opt = getopt(argc, argv, "f:gl:v?")) != -1) {
switch (opt) { switch (opt) {
case 'v': case 'v':
verbose++; verbose++;
break; break;
case 'f':
inflight_count = atoi(optarg);
break;
case 'l': case 'l':
test_loops = atoi(optarg);; test_loops = atoi(optarg);
break; break;
case 'g': case 'g':
echo_gen = 1; echo_gen = 1;
break; break;
case '?':
default: default:
print_usage(basename(argv[0])); print_usage(basename(argv[0]));
break; break;

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/* /*
* cangen.c - CAN frames generator for testing purposes * cangen.c - CAN frames generator
* *
* Copyright (c) 2002-2007 Volkswagen Group Electronic Research * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
* All rights reserved. * All rights reserved.
@ -66,6 +66,7 @@
#include "lib.h" #include "lib.h"
#define DEFAULT_GAP 200 /* ms */ #define DEFAULT_GAP 200 /* ms */
#define DEFAULT_BURST_COUNT 1
#define MODE_RANDOM 0 #define MODE_RANDOM 0
#define MODE_INCREMENT 1 #define MODE_INCREMENT 1
@ -78,17 +79,20 @@ 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, "%s - CAN frames generator.\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:\n");
fprintf(stderr, " -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, " -f (generate CAN FD CAN frames)\n"); fprintf(stderr, " -f (generate CAN FD CAN frames)\n");
fprintf(stderr, " -b (generate CAN FD CAN frames" fprintf(stderr, " -b (generate CAN FD CAN frames"
" with bitrate switch (BRS))\n"); " with bitrate switch (BRS))\n");
fprintf(stderr, " -E (generate CAN FD CAN frames"
" with error state (ESI))\n");
fprintf(stderr, " -R (send RTR frame)\n"); fprintf(stderr, " -R (send RTR frame)\n");
fprintf(stderr, " -m (mix -e -f -b -R frames)\n"); fprintf(stderr, " -m (mix -e -f -b -E -R 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)"
@ -103,28 +107,30 @@ void print_usage(char *prg)
" 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, " -c (number of messages to send in burst, "
"default 1)\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\n", prg);
fprintf(stderr, "(fixed CAN ID and length, inc. data)\n"); fprintf(stderr, "\t(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\n", prg);
fprintf(stderr, "(generate EFF frames, incr. length)\n"); fprintf(stderr, "\t(generate EFF frames, incr. length)\n");
fprintf(stderr, "%s vcan0 -D 11223344DEADBEEF -L 8 ", prg); fprintf(stderr, "%s vcan0 -D 11223344DEADBEEF -L 8\n", prg);
fprintf(stderr, "(fixed CAN data payload and length)\n"); fprintf(stderr, "\t(fixed CAN data payload and length)\n");
fprintf(stderr, "%s vcan0 -g 0 -i -x ", prg); fprintf(stderr, "%s vcan0 -g 0 -i -x\n", prg);
fprintf(stderr, "(full load test ignoring -ENOBUFS)\n"); fprintf(stderr, "\t(full load test ignoring -ENOBUFS)\n");
fprintf(stderr, "%s vcan0 -g 0 -p 10 -x ", prg); fprintf(stderr, "%s vcan0 -g 0 -p 10 -x\n", prg);
fprintf(stderr, "(full load test with polling, 10ms timeout)\n"); fprintf(stderr, "\t(full load test with polling, 10ms timeout)\n");
fprintf(stderr, "%s vcan0 ", prg); fprintf(stderr, "%s vcan0\n", prg);
fprintf(stderr, "(my favourite default :)\n\n"); fprintf(stderr, "\t(my favourite default :)\n\n");
} }
void sigterm(int signo) void sigterm(int signo)
@ -135,11 +141,13 @@ void sigterm(int signo)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
double gap = DEFAULT_GAP; double gap = DEFAULT_GAP;
unsigned long burst_count = DEFAULT_BURST_COUNT;
unsigned long polltimeout = 0; unsigned long polltimeout = 0;
unsigned char ignore_enobufs = 0; unsigned char ignore_enobufs = 0;
unsigned char extended = 0; unsigned char extended = 0;
unsigned char canfd = 0; unsigned char canfd = 0;
unsigned char brs = 0; unsigned char brs = 0;
unsigned char esi = 0;
unsigned char mix = 0; unsigned char mix = 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;
@ -148,6 +156,7 @@ int main(int argc, char **argv)
unsigned char verbose = 0; unsigned char verbose = 0;
unsigned char rtr_frame = 0; unsigned char rtr_frame = 0;
int count = 0; int count = 0;
unsigned long burst_sent_count = 0;
int mtu, maxdlen; int mtu, maxdlen;
uint64_t incdata = 0; uint64_t incdata = 0;
int incdlc = 0; int incdlc = 0;
@ -175,7 +184,7 @@ int main(int argc, char **argv)
signal(SIGHUP, sigterm); signal(SIGHUP, sigterm);
signal(SIGINT, sigterm); signal(SIGINT, sigterm);
while ((opt = getopt(argc, argv, "ig:ebfmI:L:D:xp:n:vRh?")) != -1) { while ((opt = getopt(argc, argv, "ig:ebEfmI:L:D:xp:n:c:vRh?")) != -1) {
switch (opt) { switch (opt) {
case 'i': case 'i':
@ -199,6 +208,11 @@ int main(int argc, char **argv)
canfd = 1; canfd = 1;
break; break;
case 'E':
esi = 1; /* error state indicator implies CAN FD */
canfd = 1;
break;
case 'm': case 'm':
mix = 1; mix = 1;
canfd = 1; /* to switch the socket into CAN FD mode */ canfd = 1; /* to switch the socket into CAN FD mode */
@ -240,6 +254,10 @@ int main(int argc, char **argv)
} }
break; break;
case 'c':
burst_count = strtoul(optarg, NULL, 10);
break;
case 'v': case 'v':
verbose++; verbose++;
break; break;
@ -369,6 +387,8 @@ int main(int argc, char **argv)
maxdlen = CANFD_MAX_DLEN; maxdlen = CANFD_MAX_DLEN;
if (brs) if (brs)
frame.flags |= CANFD_BRS; frame.flags |= CANFD_BRS;
if (esi)
frame.flags |= CANFD_ESI;
} else { } else {
mtu = CAN_MTU; mtu = CAN_MTU;
maxdlen = CAN_MAX_DLEN; maxdlen = CAN_MAX_DLEN;
@ -458,10 +478,14 @@ resend:
return 1; return 1;
} }
if (gap) /* gap == 0 => performance test :-] */ burst_sent_count++;
if (gap && burst_sent_count >= burst_count) /* gap == 0 => performance test :-] */
if (nanosleep(&ts, NULL)) if (nanosleep(&ts, NULL))
return 1; return 1;
if (burst_sent_count >= burst_count)
burst_sent_count = 0;
if (id_mode == MODE_INCREMENT) if (id_mode == MODE_INCREMENT)
frame.can_id++; frame.can_id++;
@ -490,8 +514,10 @@ resend:
i = random(); i = random();
extended = i&1; extended = i&1;
canfd = i&2; canfd = i&2;
if (canfd) if (canfd) {
brs = i&4; brs = i&4;
esi = i&8;
}
rtr_frame = ((i&24) == 24); /* reduce RTR frames to 1/4 */ rtr_frame = ((i&24) == 24); /* reduce RTR frames to 1/4 */
} }
} }

85
cangw.c
View File

@ -80,7 +80,7 @@ struct fdmodattr {
/* some netlink helpers stolen from iproute2 package */ /* some netlink helpers stolen from iproute2 package */
#define NLMSG_TAIL(nmsg) \ #define NLMSG_TAIL(nmsg) \
((struct rtattr *)(((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) ((struct rtattr *)(((char *) (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,
int alen) int alen)
@ -88,7 +88,7 @@ int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
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 ((int)(NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len)) > maxlen) {
fprintf(stderr, "addattr_l: message exceeded bound of %d\n", fprintf(stderr, "addattr_l: message exceeded bound of %d\n",
maxlen); maxlen);
return -1; return -1;
@ -222,55 +222,60 @@ void print_cs_crc8(struct cgw_csum_crc8 *cs_crc8)
void print_usage(char *prg) void print_usage(char *prg)
{ {
fprintf(stderr, "%s - manage PF_CAN netlink gateway.\n", prg);
fprintf(stderr, "\nUsage: %s [options]\n\n", prg); fprintf(stderr, "\nUsage: %s [options]\n\n", prg);
fprintf(stderr, "Commands: -A (add a new rule)\n"); fprintf(stderr, "Commands:\n");
fprintf(stderr, " -D (delete a rule)\n"); fprintf(stderr, " -A (add a new rule)\n");
fprintf(stderr, " -F (flush / delete all rules)\n"); fprintf(stderr, " -D (delete a rule)\n");
fprintf(stderr, " -L (list all rules)\n"); fprintf(stderr, " -F (flush / delete all rules)\n");
fprintf(stderr, "Mandatory: -s <src_dev> (source netdevice)\n"); fprintf(stderr, " -L (list all rules)\n");
fprintf(stderr, " -d <dst_dev> (destination netdevice)\n"); fprintf(stderr, "Mandatory:\n");
fprintf(stderr, "Options: -X (this is a CAN FD rule)\n"); fprintf(stderr, " -s <src_dev> (source netdevice)\n");
fprintf(stderr, " -t (preserve src_dev rx timestamp)\n"); fprintf(stderr, " -d <dst_dev> (destination netdevice)\n");
fprintf(stderr, " -e (echo sent frames - recommended on vcanx)\n"); fprintf(stderr, "Options:\n");
fprintf(stderr, " -i (allow to route to incoming interface)\n"); fprintf(stderr, " -X (this is a CAN FD rule)\n");
fprintf(stderr, " -u <uid> (user defined modification identifier)\n"); fprintf(stderr, " -t (preserve src_dev rx timestamp)\n");
fprintf(stderr, " -l <hops> (limit the number of frame hops / routings)\n"); fprintf(stderr, " -e (echo sent frames - recommended on vcanx)\n");
fprintf(stderr, " -f <filter> (set CAN filter)\n"); fprintf(stderr, " -i (allow to route to incoming interface)\n");
fprintf(stderr, " -m <mod> (set Classic CAN frame modifications)\n"); fprintf(stderr, " -u <uid> (user defined modification identifier)\n");
fprintf(stderr, " -M <MOD> (set CAN FD frame modifications)\n"); fprintf(stderr, " -l <hops> (limit the number of frame hops / routings)\n");
fprintf(stderr, " -x <from_idx>:<to_idx>:<result_idx>:<init_xor_val> (XOR checksum)\n"); fprintf(stderr, " -f <filter> (set CAN filter)\n");
fprintf(stderr, " -c <from>:<to>:<result>:<init_val>:<xor_val>:<crctab[256]> (CRC8 cs)\n"); fprintf(stderr, " -m <mod> (set Classic CAN frame modifications)\n");
fprintf(stderr, " -p <profile>:[<profile_data>] (CRC8 checksum profile & parameters)\n"); fprintf(stderr, " -M <MOD> (set CAN FD frame modifications)\n");
fprintf(stderr, " -x <from_idx>:<to_idx>:<result_idx>:<init_xor_val> (XOR checksum)\n");
fprintf(stderr, " -c <from>:<to>:<result>:<init_val>:<xor_val>:<crctab[256]> (CRC8 cs)\n");
fprintf(stderr, " -p <profile>:[<profile_data>] (CRC8 checksum profile & parameters)\n");
fprintf(stderr, "\nValues are given and expected in hexadecimal values. Leading 0s can be omitted.\n"); fprintf(stderr, "\nValues are given and expected in hexadecimal values. Leading 0s can be omitted.\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "<filter> is a <value><mask> CAN identifier filter\n"); fprintf(stderr, "<filter> is a <value><mask> CAN identifier filter:\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, " <can_id>~<can_mask> (matches when <received_can_id> & mask != can_id & mask)\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "<mod> is a CAN frame modification instruction consisting of\n"); fprintf(stderr, "<mod> is a CAN frame modification instruction consisting of\n");
fprintf(stderr, "<instruction>:<can_frame-elements>:<can_id>.<can_dlc>.<can_data>\n"); fprintf(stderr, "<instruction>:<can_frame-elements>:<can_id>.<can_dlc>.<can_data>\n");
fprintf(stderr, " - <instruction> is one of 'AND' 'OR' 'XOR' 'SET'\n"); fprintf(stderr, " <instruction> is one of 'AND' 'OR' 'XOR' 'SET'\n");
fprintf(stderr, " - <can_frame-elements> is _one_ or _more_ of 'I'dentifier 'L'ength 'D'ata\n"); fprintf(stderr, " <can_frame-elements> is _one_ or _more_ of 'I'dentifier 'L'ength 'D'ata\n");
fprintf(stderr, " - <can_id> is an u32 value containing the CAN Identifier\n"); fprintf(stderr, " <can_id> is an u32 value containing the CAN Identifier\n");
fprintf(stderr, " - <can_dlc> is an u8 value containing the data length code (0 .. 8)\n"); fprintf(stderr, " <can_dlc> is an u8 value containing the data length code (0 .. 8)\n");
fprintf(stderr, " - <can_data> is always eight(!) u8 values containing the CAN frames data\n"); fprintf(stderr, " <can_data> is always eight(!) u8 values containing the CAN frames data\n");
fprintf(stderr, "\n");
fprintf(stderr, "<MOD> is a CAN FD frame modification instruction consisting of\n"); fprintf(stderr, "<MOD> is a CAN FD frame modification instruction consisting of\n");
fprintf(stderr, "<instruction>:<canfd_frame-elements>:<can_id>.<flags>.<len>.<can_data>\n"); fprintf(stderr, "<instruction>:<canfd_frame-elements>:<can_id>.<flags>.<len>.<can_data>\n");
fprintf(stderr, " - <instruction> is one of 'AND' 'OR' 'XOR' 'SET'\n"); fprintf(stderr, " <instruction> is one of 'AND' 'OR' 'XOR' 'SET'\n");
fprintf(stderr, " - <canfd_frame-elements> is _one_ or _more_ of 'I'd 'F'lags 'L'ength 'D'ata\n"); fprintf(stderr, " <canfd_frame-elements> is _one_ or _more_ of 'I'd 'F'lags 'L'ength 'D'ata\n");
fprintf(stderr, " - <can_id> is an u32 value containing the CAN FD Identifier\n"); fprintf(stderr, " <can_id> is an u32 value containing the CAN FD Identifier\n");
fprintf(stderr, " - <flags> is an u8 value containing CAN FD flags (CANFD_BRS, CANFD_ESI)\n"); fprintf(stderr, " <flags> is an u8 value containing CAN FD flags (CANFD_BRS, CANFD_ESI)\n");
fprintf(stderr, " - <len> is an u8 value containing the data length (0 .. 64)\n"); fprintf(stderr, " <len> is an u8 value containing the data length (0 .. 64)\n");
fprintf(stderr, " - <can_data> is always 64(!) u8 values containing the CAN FD frames data\n"); fprintf(stderr, " <can_data> is always 64(!) u8 values containing the CAN FD frames data\n");
fprintf(stderr, "The max. four modifications are performed in the order AND -> OR -> XOR -> SET\n"); fprintf(stderr, "The max. four modifications are performed in the order AND -> OR -> XOR -> SET\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "Example:\n");
fprintf(stderr, "%s -A -s can0 -d vcan3 -e -f 123:C00007FF -m SET:IL:333.4.1122334455667788\n", prg);
fprintf(stderr, "\n");
fprintf(stderr, "Supported CRC 8 profiles:\n"); fprintf(stderr, "Supported CRC 8 profiles:\n");
fprintf(stderr, "Profile '%d' (1U8) - add one additional u8 value\n", CGW_CRC8PRF_1U8); fprintf(stderr, " Profile '%d' (1U8) add one additional u8 value\n", CGW_CRC8PRF_1U8);
fprintf(stderr, "Profile '%d' (16U8) - add u8 value from table[16] indexed by (data[1] & 0xF)\n", CGW_CRC8PRF_16U8); fprintf(stderr, " Profile '%d' (16U8) add u8 value from table[16] indexed by (data[1] & 0xF)\n", CGW_CRC8PRF_16U8);
fprintf(stderr, "Profile '%d' (SFFID_XOR) - add u8 value (can_id & 0xFF) ^ (can_id >> 8 & 0xFF)\n", CGW_CRC8PRF_SFFID_XOR); fprintf(stderr, " Profile '%d' (SFFID_XOR) add u8 value (can_id & 0xFF) ^ (can_id >> 8 & 0xFF)\n", CGW_CRC8PRF_SFFID_XOR);
fprintf(stderr, "\n");
fprintf(stderr, "Examples:\n");
fprintf(stderr, "%s -A -s can0 -d vcan3 -e -f 123:C00007FF -m SET:IL:333.4.1122334455667788\n", prg);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }

View File

@ -89,7 +89,8 @@ 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:\n");
fprintf(stderr, " -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");
@ -139,7 +140,7 @@ int idx2dindex(int ifidx, int socket)
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0) if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
perror("SIOCGIFNAME"); perror("SIOCGIFNAME");
if (max_devname_len < strlen(ifr.ifr_name)) if (max_devname_len < (int)strlen(ifr.ifr_name))
max_devname_len = strlen(ifr.ifr_name); max_devname_len = strlen(ifr.ifr_name);
strcpy(devname[i], ifr.ifr_name); strcpy(devname[i], ifr.ifr_name);

View File

@ -77,30 +77,32 @@ extern int optind, opterr, optopt;
void print_usage(char *prg) void print_usage(char *prg)
{ {
fprintf(stderr, "%s - replay a compact CAN frame logfile to CAN devices.\n", 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:\n");
fprintf(stderr, " -l <num> " fprintf(stderr, " -I <infile> (default stdin)\n");
"(process input file <num> times)\n" fprintf(stderr, " -l <num> "
" " "(process input file <num> times)\n"
"(Use 'i' for infinite loop - default: %d)\n", DEFAULT_LOOPS); " "
fprintf(stderr, " -t (ignore timestamps: " "(Use 'i' for infinite loop - default: %d)\n", DEFAULT_LOOPS);
"send frames immediately)\n"); fprintf(stderr, " -t (ignore timestamps: "
fprintf(stderr, " -g <ms> (gap in milli " "send frames immediately)\n");
"seconds - default: %d ms)\n", DEFAULT_GAP); fprintf(stderr, " -g <ms> (gap in milli "
fprintf(stderr, " -s <s> (skip gaps in " "seconds - default: %d ms)\n", DEFAULT_GAP);
"timestamps > 's' seconds)\n"); fprintf(stderr, " -s <s> (skip gaps in "
fprintf(stderr, " -x (disable local " "timestamps > 's' seconds)\n");
"loopback of sent CAN frames)\n"); fprintf(stderr, " -x (disable local "
fprintf(stderr, " -v (verbose: print " "loopback of sent CAN frames)\n");
"sent CAN frames)\n\n"); fprintf(stderr, " -v (verbose: print "
fprintf(stderr, "Interface assignment: 0..n assignments like " "sent CAN frames)\n\n");
"<write-if>=<log-if>\n"); fprintf(stderr, "Interface assignment:\n");
fprintf(stderr, "e.g. vcan2=can0 ( send frames received from can0 on " fprintf(stderr, " 0..n assignments like <write-if>=<log-if>\n\n");
"vcan2 )\n"); fprintf(stderr, " e.g. vcan2=can0 (send frames received from can0 on "
fprintf(stderr, "extra hook: stdout=can0 ( print logfile line marked with can0 on " "vcan2)\n");
"stdout )\n"); fprintf(stderr, " extra hook: stdout=can0 (print logfile line marked with can0 on "
fprintf(stderr, "No assignments => send frames to the interface(s) they " "stdout)\n");
"had been received from.\n\n"); fprintf(stderr, " No assignments => send frames to the interface(s) they "
"had been received from\n\n");
fprintf(stderr, "Lines in the logfile not beginning with '(' (start of " fprintf(stderr, "Lines in the logfile not beginning with '(' (start of "
"timestamp) are ignored.\n\n"); "timestamp) are ignored.\n\n");
} }
@ -357,7 +359,7 @@ int main(int argc, char **argv)
return 1; return 1;
} }
strcpy(buf, argv[optind+i]); strcpy(buf, argv[optind+i]);
for (j=0; j<BUFSZ; j++) { /* find '=' in assignment */ for (j=0; j<(int)BUFSZ; j++) { /* find '=' in assignment */
if (buf[j] == '=') if (buf[j] == '=')
break; break;
} }
@ -493,7 +495,7 @@ int main(int argc, char **argv)
/* test for logfile timestamps jumping backwards OR */ /* test for logfile timestamps jumping backwards OR */
/* if the user likes to skip long gaps in the timestamps */ /* if the user likes to skip long gaps in the timestamps */
if ((last_log_tv.tv_sec > log_tv.tv_sec) || if ((last_log_tv.tv_sec > log_tv.tv_sec) ||
(skipgap && labs(last_log_tv.tv_sec - log_tv.tv_sec) > skipgap)) (skipgap && labs(last_log_tv.tv_sec - log_tv.tv_sec) > (long)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;

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/* /*
* cansend.c - simple command line tool to send CAN-frames via CAN_RAW sockets * cansend.c - send CAN-frames via CAN_RAW sockets
* *
* Copyright (c) 2002-2007 Volkswagen Group Electronic Research * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
* All rights reserved. * All rights reserved.
@ -56,6 +56,29 @@
#include "lib.h" #include "lib.h"
void print_usage(char *prg)
{
fprintf(stderr, "%s - send CAN-frames via CAN_RAW sockets.\n", prg);
fprintf(stderr, "\nUsage: %s <device> <can_frame>.\n", prg);
fprintf(stderr, "\n<can_frame>:\n");
fprintf(stderr, " <can_id>#{data} for 'classic' CAN 2.0 data frames\n");
fprintf(stderr, " <can_id>#R{len} for 'classic' CAN 2.0 data frames\n");
fprintf(stderr, " <can_id>##<flags>{data} for CAN FD frames\n\n");
fprintf(stderr, "<can_id>:\n"
" 3 (SFF) or 8 (EFF) hex chars\n");
fprintf(stderr, "{data}:\n"
" 0..8 (0..64 CAN FD) ASCII hex-values (optionally separated by '.')\n");
fprintf(stderr, "{len}:\n"
" an optional 0..8 value as RTR frames can contain a valid dlc field\n");
fprintf(stderr, "<flags>:\n"
" a single ASCII Hex value (0 .. F) which defines canfd_frame.flags\n\n");
fprintf(stderr, "Examples:\n");
fprintf(stderr, " 5A1#11.2233.44556677.88 / 123#DEADBEEF / 5AA# / 123##1 / 213##311223344 /\n"
" 1F334455#1122334455667788 / 123#R / 00000123#R3\n\n");
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int s; /* can raw socket */ int s; /* can raw socket */
@ -68,27 +91,15 @@ int main(int argc, char **argv)
/* check command line options */ /* check command line options */
if (argc != 3) { if (argc != 3) {
fprintf(stderr, "Usage: %s <device> <can_frame>.\n", argv[0]); print_usage(argv[0]);
return 1; return 1;
} }
/* parse CAN frame */ /* parse CAN frame */
required_mtu = parse_canframe(argv[2], &frame); required_mtu = parse_canframe(argv[2], &frame);
if (!required_mtu){ if (!required_mtu){
fprintf(stderr, "\nWrong CAN-frame format! Try:\n\n"); fprintf(stderr, "\nWrong CAN-frame format!\n\n");
fprintf(stderr, " <can_id>#{data} for 'classic' CAN 2.0 data frames\n"); print_usage(argv[0]);
fprintf(stderr, " <can_id>#R{len} for 'classic' CAN 2.0 RTR frames\n");
fprintf(stderr, " <can_id>##<flags>{data} for CAN FD frames\n\n");
fprintf(stderr, "<can_id> can have 3 (SFF) or 8 (EFF) hex chars\n");
fprintf(stderr, "{data} has 0..8 (0..64 CAN FD) ASCII hex-values (optionally");
fprintf(stderr, " separated by '.')\n");
fprintf(stderr, "{len} is an optional 0..8 value as RTR frames can contain a");
fprintf(stderr, " valid dlc field\n");
fprintf(stderr, "<flags> a single ASCII Hex value (0 .. F) which defines");
fprintf(stderr, " canfd_frame.flags\n\n");
fprintf(stderr, "e.g. 5A1#11.2233.44556677.88 / 123#DEADBEEF / 5AA# / ");
fprintf(stderr, "123##1 / 213##311223344\n 1F334455#1122334455667788 / ");
fprintf(stderr, "123#R / 00000123#R3\n\n");
return 1; return 1;
} }
@ -110,7 +121,7 @@ int main(int argc, char **argv)
addr.can_family = AF_CAN; addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex; addr.can_ifindex = ifr.ifr_ifindex;
if (required_mtu > CAN_MTU) { if (required_mtu > (int)CAN_MTU) {
/* check if the frame fits into the CAN netdevice */ /* check if the frame fits into the CAN netdevice */
if (ioctl(s, SIOCGIFMTU, &ifr) < 0) { if (ioctl(s, SIOCGIFMTU, &ifr) < 0) {

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/* /*
* cansniffer.c * cansniffer.c - volatile CAN content visualizer
* *
* Copyright (c) 2002-2007 Volkswagen Group Electronic Research * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
* All rights reserved. * All rights reserved.
@ -44,6 +44,8 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <fcntl.h> #include <fcntl.h>
@ -61,13 +63,14 @@
#include <net/if.h> #include <net/if.h>
#include <linux/can.h> #include <linux/can.h>
#include <linux/can/bcm.h> #include <linux/can/raw.h>
#include <linux/sockios.h> #include <linux/sockios.h>
#include "terminal.h" #include "terminal.h"
#define SETFNAME "sniffset." #define SETFNAME "sniffset."
#define ANYDEV "any" #define ANYDEV "any"
#define MAX_SLOTS 2048
/* flags */ /* flags */
@ -92,9 +95,10 @@
#define ATTCOLOR ATTBOLD FGRED #define ATTCOLOR ATTBOLD FGRED
#define STARTLINESTR "XX delta ID data ... " #define LDL " | " /* long delimiter */
#define SDL "|" /* short delimiter for binary on 80 chars terminal */
struct snif { static struct snif {
int flags; int flags;
long hold; long hold;
long timeout; long timeout;
@ -104,75 +108,118 @@ struct snif {
struct can_frame current; struct can_frame current;
struct can_frame marker; struct can_frame marker;
struct can_frame notch; struct can_frame notch;
} sniftab[2048]; } sniftab[MAX_SLOTS];
extern int optind, opterr, optopt; extern int optind, opterr, optopt;
static int idx;
static int running = 1; static int running = 1;
static int clearscreen = 1; static int clearscreen = 1;
static int print_eff;
static int notch; static int notch;
static int filter_id_only;
static long timeout = TIMEOUT; static long timeout = TIMEOUT;
static long hold = HOLD; static long hold = HOLD;
static long loop = LOOP; static long loop = LOOP;
static unsigned char binary; static unsigned char binary;
static unsigned char binary8;
static unsigned char binary_gap; static unsigned char binary_gap;
static unsigned char color; static unsigned char color;
static char *interface; static char *interface;
static char *vdl = LDL; /* variable delimiter */
static char *ldl = LDL; /* long delimiter */
void rx_setup (int fd, int id); void print_snifline(int slot);
void rx_delete (int fd, int id); int handle_keyb(void);
void print_snifline(int id); int handle_frame(int fd, long currcms);
int handle_keyb(int fd); int handle_timeo(long currcms);
int handle_bcm(int fd, long currcms);
int handle_timeo(int fd, long currcms);
void writesettings(char* name); void writesettings(char* name);
void readsettings(char* name, int sockfd); int readsettings(char* name);
int sniftab_index(canid_t id);
void switchvdl(char *delim)
{
/* reduce delimiter size for EFF IDs in binary display of up
to 8 data bytes payload to fit into 80 chars per line */
if (binary8)
vdl = delim;
}
int comp(const void *elem1, const void *elem2)
{
unsigned long f = ((struct snif*)elem1)->current.can_id;
unsigned long s = ((struct snif*)elem2)->current.can_id;
if (f > s)
return 1;
if (f < s)
return -1;
return 0;
}
void print_usage(char *prg) void print_usage(char *prg)
{ {
const char manual [] = { const char manual [] = {
"commands that can be entered at runtime:\n" "commands that can be entered at runtime:\n"
"\n" " q<ENTER> - quit\n"
"q<ENTER> - quit\n" " b<ENTER> - toggle binary / HEX-ASCII output\n"
"b<ENTER> - toggle binary / HEX-ASCII output\n" " 8<ENTER> - toggle binary / HEX-ASCII output (small for EFF on 80 chars)\n"
"B<ENTER> - toggle binary with gap / HEX-ASCII output (exceeds 80 chars!)\n" " B<ENTER> - toggle binary with gap / HEX-ASCII output (exceeds 80 chars!)\n"
"c<ENTER> - toggle color mode\n" " c<ENTER> - toggle color mode\n"
"#<ENTER> - notch currently marked/changed bits (can be used repeatedly)\n" " <SPACE><ENTER> - force a clear screen\n"
"*<ENTER> - clear notched marked\n" " #<ENTER> - notch currently marked/changed bits (can be used repeatedly)\n"
"rMYNAME<ENTER> - read settings file (filter/notch)\n" " *<ENTER> - clear notched marked\n"
"wMYNAME<ENTER> - write settings file (filter/notch)\n" " rMYNAME<ENTER> - read settings file (filter/notch)\n"
"+FILTER<ENTER> - add CAN-IDs to sniff\n" " wMYNAME<ENTER> - write settings file (filter/notch)\n"
"-FILTER<ENTER> - remove CAN-IDs to sniff\n" " a<ENTER> - enable 'a'll SFF CAN-IDs to sniff\n"
" n<ENTER> - enable 'n'one SFF CAN-IDs to sniff\n"
" A<ENTER> - enable 'A'll EFF CAN-IDs to sniff\n"
" N<ENTER> - enable 'N'one EFF CAN-IDs to sniff\n"
" +FILTER<ENTER> - add CAN-IDs to sniff\n"
" -FILTER<ENTER> - remove CAN-IDs to sniff\n"
"\n" "\n"
"FILTER can be a single CAN-ID or a CAN-ID/Bitmask:\n" "FILTER can be a single CAN-ID or a CAN-ID/Bitmask:\n"
"+1F5<ENTER> - add CAN-ID 0x1F5\n" "\n"
"-42E<ENTER> - remove CAN-ID 0x42E\n" " single SFF 11 bit IDs:\n"
"-42E7FF<ENTER> - remove CAN-ID 0x42E (using Bitmask)\n" " +1F5<ENTER> - add SFF CAN-ID 0x1F5\n"
"-500700<ENTER> - remove CAN-IDs 0x500 - 0x5FF\n" " -42E<ENTER> - remove SFF CAN-ID 0x42E\n"
"+400600<ENTER> - add CAN-IDs 0x400 - 0x5FF\n" "\n"
"+000000<ENTER> - add all CAN-IDs\n" " single EFF 29 bit IDs:\n"
"-000000<ENTER> - remove all CAN-IDs\n" " +18FEDF55<ENTER> - add EFF CAN-ID 0x18FEDF55\n"
" -00000090<ENTER> - remove EFF CAN-ID 0x00000090\n"
"\n"
" CAN-ID/Bitmask SFF:\n"
" -42E7FF<ENTER> - remove SFF CAN-ID 0x42E (using Bitmask)\n"
" -500700<ENTER> - remove SFF CAN-IDs 0x500 - 0x5FF\n"
" +400600<ENTER> - add SFF CAN-IDs 0x400 - 0x5FF\n"
" +000000<ENTER> - add all SFF CAN-IDs\n"
" -000000<ENTER> - remove all SFF CAN-IDs\n"
"\n"
" CAN-ID/Bitmask EFF:\n"
" -0000000000000000<ENTER> - remove all EFF CAN-IDs\n"
" +12345678000000FF<ENTER> - add EFF CAN IDs xxxxxx78\n"
" +0000000000000000<ENTER> - add all EFF CAN-IDs\n"
"\n" "\n"
"if (id & filter) == (sniff-id & filter) the action (+/-) is performed,\n" "if (id & filter) == (sniff-id & filter) the action (+/-) is performed,\n"
"which is quite easy when the filter is 000\n" "which is quite easy when the filter is 000 resp. 00000000 for EFF.\n"
"\n" "\n"
}; };
fprintf(stderr, "%s - volatile CAN content visualizer.\n", prg);
fprintf(stderr, "\nUsage: %s [can-interface]\n", prg); fprintf(stderr, "\nUsage: %s [can-interface]\n", prg);
fprintf(stderr, "Options: -m <mask> (initial FILTER default 0x00000000)\n"); fprintf(stderr, "Options:\n");
fprintf(stderr, " -v <value> (initial FILTER default 0x00000000)\n"); fprintf(stderr, " -q (quiet - all IDs deactivated)\n");
fprintf(stderr, " -q (quiet - all IDs deactivated)\n"); fprintf(stderr, " -r <name> (read %sname from file)\n", SETFNAME);
fprintf(stderr, " -r <name> (read %sname from file)\n", SETFNAME); fprintf(stderr, " -e (fix extended frame format output - no auto detect)\n");
fprintf(stderr, " -b (start with binary mode)\n"); fprintf(stderr, " -b (start with binary mode)\n");
fprintf(stderr, " -B (start with binary mode with gap - exceeds 80 chars!)\n"); fprintf(stderr, " -8 (start with binary mode - for EFF on 80 chars)\n");
fprintf(stderr, " -c (color changes)\n"); fprintf(stderr, " -B (start with binary mode with gap - exceeds 80 chars!)\n");
fprintf(stderr, " -f (filter on CAN-ID only)\n"); fprintf(stderr, " -c (color changes)\n");
fprintf(stderr, " -t <time> (timeout for ID display [x10ms] default: %d, 0 = OFF)\n", TIMEOUT); fprintf(stderr, " -t <time> (timeout for ID display [x10ms] default: %d, 0 = OFF)\n", TIMEOUT);
fprintf(stderr, " -h <time> (hold marker on changes [x10ms] default: %d)\n", HOLD); fprintf(stderr, " -h <time> (hold marker on changes [x10ms] default: %d)\n", HOLD);
fprintf(stderr, " -l <time> (loop time (display) [x10ms] default: %d)\n", LOOP); fprintf(stderr, " -l <time> (loop time (display) [x10ms] default: %d)\n", LOOP);
fprintf(stderr, "Use interface name '%s' to receive from all can-interfaces\n", ANYDEV); fprintf(stderr, " -? (print this help text)\n");
fprintf(stderr, "Use interface name '%s' to receive from all can-interfaces.\n", ANYDEV);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "%s", manual); fprintf(stderr, "%s", manual);
} }
@ -186,37 +233,28 @@ int main(int argc, char **argv)
{ {
fd_set rdfs; fd_set rdfs;
int s; int s;
canid_t mask = 0;
canid_t value = 0;
long currcms = 0; long currcms = 0;
long lastcms = 0; long lastcms = 0;
unsigned char quiet = 0; unsigned char quiet = 0;
int opt, ret; int opt, ret;
struct timeval timeo, start_tv, tv; struct timeval timeo, start_tv, tv;
struct sockaddr_can addr; struct sockaddr_can addr;
struct ifreq ifr;
int i; int i;
signal(SIGTERM, sigterm); signal(SIGTERM, sigterm);
signal(SIGHUP, sigterm); signal(SIGHUP, sigterm);
signal(SIGINT, sigterm); signal(SIGINT, sigterm);
for (i=0; i < 2048 ;i++) /* default: check all CAN-IDs */ for (i = 0; i < MAX_SLOTS ;i++) /* default: enable all slots */
do_set(i, ENABLE); do_set(i, ENABLE);
while ((opt = getopt(argc, argv, "m:v:r:t:h:l:qbBcf?")) != -1) { while ((opt = getopt(argc, argv, "r:t:h:l:qeb8Bc?")) != -1) {
switch (opt) { switch (opt) {
case 'm':
sscanf(optarg, "%x", &mask);
break;
case 'v':
sscanf(optarg, "%x", &value);
break;
case 'r': case 'r':
readsettings(optarg, 0); /* no BCM-setting here */ if (readsettings(optarg) < 0) {
fprintf(stderr, "Unable to read setting file '%s%s'!\n", SETFNAME, optarg);
exit(1);
}
break; break;
case 't': case 't':
@ -235,11 +273,22 @@ int main(int argc, char **argv)
quiet = 1; quiet = 1;
break; break;
case 'e':
print_eff = 1;
break;
case 'b': case 'b':
binary = 1; binary = 1;
binary_gap = 0; binary_gap = 0;
break; break;
case '8':
binary = 1;
binary8 = 1; /* enable variable delimiter for EFF */
switchvdl(SDL); /* switch directly to short delimiter */
binary_gap = 0;
break;
case 'B': case 'B':
binary = 1; binary = 1;
binary_gap = 1; binary_gap = 1;
@ -249,11 +298,9 @@ int main(int argc, char **argv)
color = 1; color = 1;
break; break;
case 'f':
filter_id_only = 1;
break;
case '?': case '?':
print_usage(basename(argv[0]));
exit(0);
break; break;
default: default:
@ -268,16 +315,8 @@ int main(int argc, char **argv)
} }
if (quiet) if (quiet)
for (i = 0; i < 2048; i++) for (i = 0; i < MAX_SLOTS; i++)
do_clr(i, ENABLE); do_clr(i, ENABLE);
else if (mask || value) {
for (i=0; i < 2048 ;i++) {
if ((i & mask) == (value & mask))
do_set(i, ENABLE);
else
do_clr(i, ENABLE);
}
}
if (strlen(argv[optind]) >= IFNAMSIZ) { if (strlen(argv[optind]) >= IFNAMSIZ) {
printf("name of CAN device '%s' is too long!\n", argv[optind]); printf("name of CAN device '%s' is too long!\n", argv[optind]);
@ -286,33 +325,24 @@ int main(int argc, char **argv)
interface = argv[optind]; interface = argv[optind];
if ((s = socket(PF_CAN, SOCK_DGRAM, CAN_BCM)) < 0) { s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (s < 0) {
perror("socket"); perror("socket");
return 1; return 1;
} }
addr.can_family = AF_CAN; addr.can_family = AF_CAN;
if (strcmp(ANYDEV, argv[optind])) { if (strcmp(ANYDEV, argv[optind]))
strcpy(ifr.ifr_name, argv[optind]); addr.can_ifindex = if_nametoindex(argv[optind]);
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX");
exit(1);
}
addr.can_ifindex = ifr.ifr_ifindex;
}
else else
addr.can_ifindex = 0; /* any can interface */ addr.can_ifindex = 0; /* any can interface */
if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("connect"); perror("connect");
return 1; return 1;
} }
for (i=0; i < 2048 ;i++) /* initial BCM setup */
if (is_set(i, ENABLE))
rx_setup(s, i);
gettimeofday(&start_tv, NULL); gettimeofday(&start_tv, NULL);
tv.tv_sec = tv.tv_usec = 0; tv.tv_sec = tv.tv_usec = 0;
@ -337,13 +367,13 @@ int main(int argc, char **argv)
currcms = (tv.tv_sec - start_tv.tv_sec) * 100 + (tv.tv_usec / 10000); currcms = (tv.tv_sec - start_tv.tv_sec) * 100 + (tv.tv_usec / 10000);
if (FD_ISSET(0, &rdfs)) if (FD_ISSET(0, &rdfs))
running &= handle_keyb(s); running &= handle_keyb();
if (FD_ISSET(s, &rdfs)) if (FD_ISSET(s, &rdfs))
running &= handle_bcm(s, currcms); running &= handle_frame(s, currcms);
if (currcms - lastcms >= loop) { if (currcms - lastcms >= loop) {
running &= handle_timeo(s, currcms); running &= handle_timeo(currcms);
lastcms = currcms; lastcms = currcms;
} }
} }
@ -354,85 +384,99 @@ int main(int argc, char **argv)
return 0; return 0;
} }
void rx_setup (int fd, int id){ void do_modify_sniftab(unsigned int value, unsigned int mask, char cmd)
{
int i;
struct { for (i = 0; i < idx ;i++) {
struct bcm_msg_head msg_head; if ((sniftab[i].current.can_id & mask) == (value & mask)) {
struct can_frame frame; if (cmd == '+')
} txmsg; do_set(i, ENABLE);
else
txmsg.msg_head.opcode = RX_SETUP; do_clr(i, ENABLE);
txmsg.msg_head.can_id = id; }
txmsg.msg_head.flags = RX_CHECK_DLC; }
txmsg.msg_head.ival1.tv_sec = 0;
txmsg.msg_head.ival1.tv_usec = 0;
txmsg.msg_head.ival2.tv_sec = 0;
txmsg.msg_head.ival2.tv_usec = 0;
txmsg.msg_head.nframes = 1;
/* set all bits to be relevant */
memset(&txmsg.frame.data, 0xFF, 8);
if (filter_id_only)
txmsg.msg_head.flags |= RX_FILTER_ID;
if (write(fd, &txmsg, sizeof(txmsg)) < 0)
perror("write");
};
void rx_delete (int fd, int id){
struct bcm_msg_head msg_head;
msg_head.opcode = RX_DELETE;
msg_head.can_id = id;
msg_head.nframes = 0;
if (write(fd, &msg_head, sizeof(msg_head)) < 0)
perror("write");
} }
int handle_keyb(int fd){ int handle_keyb(void)
{
char cmd [20] = {0}; char cmd [25] = {0};
int i; int i, clen;
unsigned int mask; unsigned int mask;
unsigned int value; unsigned int value;
if (read(0, cmd, 19) > strlen("+123456\n")) if (read(0, cmd, 24) > (long)strlen("+1234567812345678\n"))
return 1; /* ignore */ return 1; /* ignore */
if (strlen(cmd) > 0) if (strlen(cmd) > 0)
cmd[strlen(cmd)-1] = 0; /* chop off trailing newline */ cmd[strlen(cmd)-1] = 0; /* chop off trailing newline */
clen = strlen(&cmd[1]); /* content length behind command */
switch (cmd[0]) { switch (cmd[0]) {
case '+': case '+':
case '-': case '-':
sscanf(&cmd[1], "%x", &value); if (clen == 6) {
if (strlen(&cmd[1]) > 3) { /* masking strict SFF ID content vvvmmm */
mask = value & 0xFFF; sscanf(&cmd[1], "%x", &value);
mask = value | 0xFFFF800; /* cleared flags! */
value >>= 12; value >>= 12;
value &= 0x7FF;
do_modify_sniftab(value, mask, cmd[0]);
break;
} else if (clen == 16) {
sscanf(&cmd[9], "%x", &mask);
cmd[9] = 0; /* terminate 'value' */
sscanf(&cmd[1], "%x", &value);
mask |= CAN_EFF_FLAG;
value |= CAN_EFF_FLAG;
do_modify_sniftab(value, mask, cmd[0]);
break;
} }
else
mask = 0x7FF;
if (cmd[0] == '+') { /* check for single SFF/EFF CAN ID length */
for (i=0; i < 2048 ;i++) { if (!((clen == 3) || (clen == 8)))
if (((i & mask) == (value & mask)) && (is_clr(i, ENABLE))) { break;
do_set(i, ENABLE);
rx_setup(fd, i); /* enable/disable single SFF/EFF CAN ID */
} sscanf(&cmd[1], "%x", &value);
} if (clen == 8)
} value |= CAN_EFF_FLAG;
else { /* '-' */
for (i=0; i < 2048 ;i++) { i = sniftab_index(value);
if (((i & mask) == (value & mask)) && (is_set(i, ENABLE))) { if (i < 0)
do_clr(i, ENABLE); break; /* No Match */
rx_delete(fd, i);
} if (cmd[0] == '+')
} do_set(i, ENABLE);
} else
do_clr(i, ENABLE);
break;
case 'a' : /* all SFF CAN IDs */
value = 0;
mask = 0xFFFF800; /* cleared flags! */
do_modify_sniftab(value, mask, '+');
break;
case 'n' : /* none SFF CAN IDs */
value = 0;
mask = 0xFFFF800; /* cleared flags! */
do_modify_sniftab(value, mask, '-');
break;
case 'A' : /* all EFF CAN IDs */
value = CAN_EFF_FLAG;
mask = CAN_EFF_FLAG;
do_modify_sniftab(value, mask, '+');
break;
case 'N' : /* none EFF CAN IDs */
value = CAN_EFF_FLAG;
mask = CAN_EFF_FLAG;
do_modify_sniftab(value, mask, '-');
break; break;
case 'w' : case 'w' :
@ -440,7 +484,7 @@ int handle_keyb(int fd){
break; break;
case 'r' : case 'r' :
readsettings(&cmd[1], fd); readsettings(&cmd[1]); /* don't care about success */
break; break;
case 'q' : case 'q' :
@ -449,6 +493,7 @@ int handle_keyb(int fd){
case 'B' : case 'B' :
binary_gap = 1; binary_gap = 1;
switchvdl(LDL);
if (binary) if (binary)
binary = 0; binary = 0;
else else
@ -456,13 +501,19 @@ int handle_keyb(int fd){
break; break;
case '8' :
binary8 = 1;
/* fallthrough */
case 'b' : case 'b' :
binary_gap = 0; binary_gap = 0;
if (binary) if (binary) {
binary = 0; binary = 0;
else switchvdl(LDL);
} else {
binary = 1; binary = 1;
switchvdl(SDL);
}
break; break;
case 'c' : case 'c' :
@ -473,12 +524,16 @@ int handle_keyb(int fd){
break; break;
case ' ' :
clearscreen = 1;
break;
case '#' : case '#' :
notch = 1; notch = 1;
break; break;
case '*' : case '*' :
for (i=0; i < 2048; i++) for (i = 0; i < idx; i++)
memset(&sniftab[i].notch.data, 0, 8); memset(&sniftab[i].notch.data, 0, 8);
break; break;
@ -491,66 +546,102 @@ int handle_keyb(int fd){
return 1; /* ok */ return 1; /* ok */
}; };
int handle_bcm(int fd, long currcms){ int handle_frame(int fd, long currcms)
{
bool rx_changed = false;
bool run_qsort = false;
int nbytes, i, pos;
struct can_frame cf;
int nbytes, id, i; if ((nbytes = read(fd, &cf, sizeof(cf))) < 0) {
perror("raw read");
struct {
struct bcm_msg_head msg_head;
struct can_frame frame;
} bmsg;
if ((nbytes = read(fd, &bmsg, sizeof(bmsg))) < 0) {
perror("bcm read");
return 0; /* quit */ return 0; /* quit */
} }
id = bmsg.msg_head.can_id; if (nbytes != CAN_MTU) {
ioctl(fd, SIOCGSTAMP, &sniftab[id].currstamp); printf("received strange frame data length %d!\n", nbytes);
if (bmsg.msg_head.opcode != RX_CHANGED) {
printf("received strange BCM opcode %d!\n", bmsg.msg_head.opcode);
return 0; /* quit */ return 0; /* quit */
} }
if (nbytes != sizeof(bmsg)) { if (!print_eff && (cf.can_id & CAN_EFF_FLAG)) {
printf("received strange BCM data length %d!\n", nbytes); print_eff = 1;
return 0; /* quit */ clearscreen = 1;
} }
sniftab[id].current = bmsg.frame; pos = sniftab_index(cf.can_id);
for (i=0; i < 8; i++) if (pos < 0) {
sniftab[id].marker.data[i] |= sniftab[id].current.data[i] ^ sniftab[id].last.data[i]; /* CAN ID not existing */
if (idx < MAX_SLOTS) {
/* assign new slot */
pos = idx++;
rx_changed = true;
run_qsort = true;
} else {
/* informative exit */
perror("number of different CAN IDs exceeded MAX_SLOTS");
return 0; /* quit */
}
}
else {
if (cf.can_dlc == sniftab[pos].current.can_dlc)
for (i = 0; i < cf.can_dlc; i++) {
if (cf.data[i] != sniftab[pos].current.data[i] ) {
rx_changed = true;
break;
}
}
else
rx_changed = true;
}
sniftab[id].timeout = (timeout)?(currcms + timeout):0; /* print received frame even if the data didn't change to get a gap time */
if ((sniftab[pos].laststamp.tv_sec == 0) && (sniftab[pos].laststamp.tv_usec == 0))
rx_changed = true;
if (is_clr(id, DISPLAY)) if (rx_changed == true) {
clearscreen = 1; /* new entry -> new drawing */ sniftab[pos].laststamp = sniftab[pos].currstamp;
ioctl(fd, SIOCGSTAMP, &sniftab[pos].currstamp);
do_set(id, DISPLAY); sniftab[pos].current = cf;
do_set(id, UPDATE); for (i = 0; i < 8; i++)
sniftab[pos].marker.data[i] |= sniftab[pos].current.data[i] ^ sniftab[pos].last.data[i];
sniftab[pos].timeout = (timeout)?(currcms + timeout):0;
if (is_clr(pos, DISPLAY))
clearscreen = 1; /* new entry -> new drawing */
do_set(pos, DISPLAY);
do_set(pos, UPDATE);
}
if (run_qsort == true)
qsort(sniftab, idx, sizeof(sniftab[0]), comp);
return 1; /* ok */ return 1; /* ok */
}; };
int handle_timeo(int fd, long currcms){ int handle_timeo(long currcms)
{
int i, j; int i, j;
int force_redraw = 0; int force_redraw = 0;
static unsigned int frame_count; static unsigned int frame_count;
if (clearscreen) { if (clearscreen) {
char startline[80]; if (print_eff)
printf("%s%s", CLR_SCREEN, CSR_HOME); printf("%s%sXX|ms%s-- ID --%sdata ... < %s # l=%ld h=%ld t=%ld slots=%d >",
snprintf(startline, 79, "< cansniffer %s # l=%ld h=%ld t=%ld >", interface, loop, hold, timeout); CLR_SCREEN, CSR_HOME, vdl, vdl, interface, loop, hold, timeout, idx);
printf("%s%*s",STARTLINESTR, 79-(int)strlen(STARTLINESTR), startline); else
printf("%s%sXX|ms%sID %sdata ... < %s # l=%ld h=%ld t=%ld slots=%d >",
CLR_SCREEN, CSR_HOME, ldl, ldl, interface, loop, hold, timeout, idx);
force_redraw = 1; force_redraw = 1;
clearscreen = 0; clearscreen = 0;
} }
if (notch) { if (notch) {
for (i=0; i < 2048; i++) { for (i = 0; i < idx; i++) {
for (j=0; j < 8; j++) for (j = 0; j < 8; j++)
sniftab[i].notch.data[j] |= sniftab[i].marker.data[j]; sniftab[i].notch.data[j] |= sniftab[i].marker.data[j];
} }
notch = 0; notch = 0;
@ -560,25 +651,21 @@ int handle_timeo(int fd, long currcms){
printf("%02d\n", frame_count++); /* rolling display update counter */ printf("%02d\n", frame_count++); /* rolling display update counter */
frame_count %= 100; frame_count %= 100;
for (i=0; i < 2048; i++) { for (i = 0; i < idx; i++) {
if is_set(i, ENABLE) { if is_set(i, ENABLE) {
if is_set(i, DISPLAY) { if is_set(i, DISPLAY) {
if (is_set(i, UPDATE) || (force_redraw)) {
if (is_set(i, UPDATE) || (force_redraw)){
print_snifline(i); print_snifline(i);
sniftab[i].hold = currcms + hold; sniftab[i].hold = currcms + hold;
do_clr(i, UPDATE); do_clr(i, UPDATE);
} }
else else if ((sniftab[i].hold) && (sniftab[i].hold < currcms)) {
if ((sniftab[i].hold) && (sniftab[i].hold < currcms)) {
memset(&sniftab[i].marker.data, 0, 8); memset(&sniftab[i].marker.data, 0, 8);
print_snifline(i); print_snifline(i);
sniftab[i].hold = 0; /* disable update by hold */ sniftab[i].hold = 0; /* disable update by hold */
} }
else else
printf("%s", CSR_DOWN); /* skip my line */ printf("%s", CSR_DOWN); /* skip my line */
if (sniftab[i].timeout && sniftab[i].timeout < currcms) { if (sniftab[i].timeout && sniftab[i].timeout < currcms) {
do_clr(i, DISPLAY); do_clr(i, DISPLAY);
@ -587,19 +674,18 @@ int handle_timeo(int fd, long currcms){
} }
} }
sniftab[i].last = sniftab[i].current; sniftab[i].last = sniftab[i].current;
sniftab[i].laststamp = sniftab[i].currstamp;
} }
} }
return 1; /* ok */ return 1; /* ok */
}; };
void print_snifline(int id){ void print_snifline(int slot)
{
long diffsec = sniftab[id].currstamp.tv_sec - sniftab[id].laststamp.tv_sec; long diffsec = sniftab[slot].currstamp.tv_sec - sniftab[slot].laststamp.tv_sec;
long diffusec = sniftab[id].currstamp.tv_usec - sniftab[id].laststamp.tv_usec; long diffusec = sniftab[slot].currstamp.tv_usec - sniftab[slot].laststamp.tv_usec;
int dlc_diff = sniftab[id].last.can_dlc - sniftab[id].current.can_dlc; int dlc_diff = sniftab[slot].last.can_dlc - sniftab[slot].current.can_dlc;
canid_t cid = sniftab[slot].current.can_id;
int i,j; int i,j;
if (diffusec < 0) if (diffusec < 0)
@ -608,23 +694,27 @@ void print_snifline(int id){
if (diffsec < 0) if (diffsec < 0)
diffsec = diffusec = 0; diffsec = diffusec = 0;
if (diffsec > 10) if (diffsec >= 100)
diffsec = 9, diffusec = 999999; diffsec = 99, diffusec = 999999;
printf("%ld.%06ld %3X ", diffsec, diffusec, id); if (cid & CAN_EFF_FLAG)
printf("%02ld%03ld%s%08X%s", diffsec, diffusec/1000, vdl, cid & CAN_EFF_MASK, vdl);
else if (print_eff)
printf("%02ld%03ld%s---- %03X%s", diffsec, diffusec/1000, vdl, cid & CAN_SFF_MASK, vdl);
else
printf("%02ld%03ld%s%03X%s", diffsec, diffusec/1000, ldl, cid & CAN_SFF_MASK, ldl);
if (binary) { if (binary) {
for (i = 0; i < sniftab[slot].current.can_dlc; i++) {
for (i=0; i<sniftab[id].current.can_dlc; i++) { for (j=7; j >= 0; j--) {
for (j=7; j>=0; j--) { if ((color) && (sniftab[slot].marker.data[i] & 1<<j) &&
if ((color) && (sniftab[id].marker.data[i] & 1<<j) && (!(sniftab[slot].notch.data[i] & 1<<j)))
(!(sniftab[id].notch.data[i] & 1<<j))) if (sniftab[slot].current.data[i] & 1<<j)
if (sniftab[id].current.data[i] & 1<<j)
printf("%s1%s", ATTCOLOR, ATTRESET); printf("%s1%s", ATTCOLOR, ATTRESET);
else else
printf("%s0%s", ATTCOLOR, ATTRESET); printf("%s0%s", ATTCOLOR, ATTRESET);
else else
if (sniftab[id].current.data[i] & 1<<j) if (sniftab[slot].current.data[i] & 1<<j)
putchar('1'); putchar('1');
else else
putchar('0'); putchar('0');
@ -637,30 +727,29 @@ void print_snifline(int id){
* when the can_dlc decreased (dlc_diff > 0), * when the can_dlc decreased (dlc_diff > 0),
* we need to blank the former data printout * we need to blank the former data printout
*/ */
for (i=0; i<dlc_diff; i++) { for (i = 0; i < dlc_diff; i++) {
printf(" "); printf(" ");
if (binary_gap) if (binary_gap)
putchar(' '); putchar(' ');
} }
} }
else { else {
for (i = 0; i < sniftab[slot].current.can_dlc; i++)
for (i=0; i<sniftab[id].current.can_dlc; i++) if ((color) && (sniftab[slot].marker.data[i] & ~sniftab[slot].notch.data[i]))
if ((color) && (sniftab[id].marker.data[i]) && (!(sniftab[id].notch.data[i]))) printf("%s%02X%s ", ATTCOLOR, sniftab[slot].current.data[i], ATTRESET);
printf("%s%02X%s ", ATTCOLOR, sniftab[id].current.data[i], ATTRESET);
else else
printf("%02X ", sniftab[id].current.data[i]); printf("%02X ", sniftab[slot].current.data[i]);
if (sniftab[id].current.can_dlc < 8) if (sniftab[slot].current.can_dlc < 8)
printf("%*s", (8 - sniftab[id].current.can_dlc) * 3, ""); printf("%*s", (8 - sniftab[slot].current.can_dlc) * 3, "");
for (i=0; i<sniftab[id].current.can_dlc; i++) for (i = 0; i<sniftab[slot].current.can_dlc; i++)
if ((sniftab[id].current.data[i] > 0x1F) && if ((sniftab[slot].current.data[i] > 0x1F) &&
(sniftab[id].current.data[i] < 0x7F)) (sniftab[slot].current.data[i] < 0x7F))
if ((color) && (sniftab[id].marker.data[i]) && (!(sniftab[id].notch.data[i]))) if ((color) && (sniftab[slot].marker.data[i] & ~sniftab[slot].notch.data[i]))
printf("%s%c%s", ATTCOLOR, sniftab[id].current.data[i], ATTRESET); printf("%s%c%s", ATTCOLOR, sniftab[slot].current.data[i], ATTRESET);
else else
putchar(sniftab[id].current.data[i]); putchar(sniftab[slot].current.data[i]);
else else
putchar('.'); putchar('.');
@ -668,40 +757,38 @@ void print_snifline(int id){
* when the can_dlc decreased (dlc_diff > 0), * when the can_dlc decreased (dlc_diff > 0),
* we need to blank the former data printout * we need to blank the former data printout
*/ */
for (i=0; i<dlc_diff; i++) for (i = 0; i < dlc_diff; i++)
putchar(' '); putchar(' ');
} }
putchar('\n'); putchar('\n');
memset(&sniftab[id].marker.data, 0, 8); memset(&sniftab[slot].marker.data, 0, 8);
}; };
void writesettings(char* name)
void writesettings(char* name){ {
int fd; int fd;
char fname[30] = SETFNAME; char fname[30] = SETFNAME;
int i,j; int i,j;
char buf[8]= {0}; char buf[13]= {0};
strncat(fname, name, 29 - strlen(fname)); strncat(fname, name, 29 - strlen(fname));
fd = open(fname, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); fd = open(fname, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
if (fd > 0) { if (fd > 0) {
for (i = 0; i < idx ;i++) {
for (i=0; i < 2048 ;i++) { sprintf(buf, "<%08X>%c.", sniftab[i].current.can_id, (is_set(i, ENABLE))?'1':'0');
sprintf(buf, "<%03X>%c.", i, (is_set(i, ENABLE))?'1':'0'); if (write(fd, buf, 12) < 0)
if (write(fd, buf, 7) < 0)
perror("write"); perror("write");
for (j=0; j<8 ; j++){ for (j = 0; j < 8 ; j++) {
sprintf(buf, "%02X", sniftab[i].notch.data[j]); sprintf(buf, "%02X", sniftab[i].notch.data[j]);
if (write(fd, buf, 2) < 0) if (write(fd, buf, 2) < 0)
perror("write"); perror("write");
} }
if (write(fd, "\n", 1) < 0) if (write(fd, "\n", 1) < 0)
perror("write"); perror("write");
/* 7 + 16 + 1 = 24 bytes per entry */ /* 12 + 16 + 1 = 29 bytes per entry */
} }
close(fd); close(fd);
} }
@ -709,53 +796,57 @@ void writesettings(char* name){
printf("unable to write setting file '%s'!\n", fname); printf("unable to write setting file '%s'!\n", fname);
}; };
void readsettings(char* name, int sockfd){ int readsettings(char* name)
{
int fd; int fd;
char fname[30] = SETFNAME; char fname[30] = SETFNAME;
char buf[25] = {0}; char buf[30] = {0};
int i,j; int j;
bool done = false;
strncat(fname, name, 29 - strlen(fname)); strncat(fname, name, 29 - strlen(fname));
fd = open(fname, O_RDONLY); fd = open(fname, O_RDONLY);
if (fd > 0) { if (fd > 0) {
if (!sockfd) idx = 0;
printf("reading setting file '%s' ... ", fname); while (!done) {
if (read(fd, &buf, 29) == 29) {
unsigned long id = strtoul(&buf[1], (char **)NULL, 16);
for (i=0; i < 2048 ;i++) { sniftab[idx].current.can_id = id;
if (read(fd, &buf, 24) == 24) {
if (buf[5] & 1) { if (buf[10] & 1)
if (is_clr(i, ENABLE)) { do_set(idx, ENABLE);
do_set(i, ENABLE);
if (sockfd)
rx_setup(sockfd, i);
}
}
else else
if (is_set(i, ENABLE)) { do_clr(idx, ENABLE);
do_clr(i, ENABLE);
if (sockfd) for (j = 7; j >= 0 ; j--) {
rx_delete(sockfd, i); sniftab[idx].notch.data[j] =
} (__u8) strtoul(&buf[2*j+12], (char **)NULL, 16) & 0xFF;
for (j=7; j>=0 ; j--){ buf[2*j+12] = 0; /* cut off each time */
sniftab[i].notch.data[j] =
(__u8) strtoul(&buf[2*j+7], (char **)NULL, 16) & 0xFF;
buf[2*j+7] = 0; /* cut off each time */
} }
if (++idx >= MAX_SLOTS)
break;
} }
else { else
if (!sockfd) done = true;
printf("was only able to read until index %d from setting file '%s'!\n",
i, fname);
}
} }
if (!sockfd)
printf("done\n");
close(fd); close(fd);
} }
else else
printf("unable to read setting file '%s'!\n", fname); return -1;
return idx;
}; };
int sniftab_index(canid_t id)
{
int i;
for (i = 0; i <= idx; i++)
if (id == sniftab[i].current.can_id)
return i;
return -1; /* No match */
}

View File

@ -96,7 +96,7 @@ struct nlmsghdr {
(struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len))) (struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \ #define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \
(nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \ (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
(nlh)->nlmsg_len <= (len)) (int)((nlh)->nlmsg_len) <= (len))
#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len))) #define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
#define NLMSG_NOOP 0x1 /* Nothing. */ #define NLMSG_NOOP 0x1 /* Nothing. */

View File

@ -68,20 +68,23 @@ const int canfd_on = 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, "Options: -s <can_id> (source can_id. Use 8 digits for extended IDs)\n"); fprintf(stderr, "Options:\n");
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n"); fprintf(stderr, " -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
fprintf(stderr, " -x <addr> (extended addressing mode. Use 'any' for all addresses)\n"); fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
fprintf(stderr, " -X <addr> (extended addressing mode (rx addr). Use 'any' for all)\n"); fprintf(stderr, " -x <addr> (extended addressing mode. Use 'any' for all addresses)\n");
fprintf(stderr, " -c (color mode)\n"); fprintf(stderr, " -X <addr> (extended addressing mode (rx addr). Use 'any' for all)\n");
fprintf(stderr, " -a (print data also in ASCII-chars)\n"); fprintf(stderr, " -c (color mode)\n");
fprintf(stderr, " -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n"); fprintf(stderr, " -a (print data also in ASCII-chars)\n");
fprintf(stderr, " -u (print uds messages)\n"); fprintf(stderr, " -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n");
fprintf(stderr, " -u (print uds messages)\n");
fprintf(stderr, "\nCAN IDs and addresses are given and expected in hexadecimal values.\n"); fprintf(stderr, "\nCAN IDs and addresses are given and expected in hexadecimal values.\n");
fprintf(stderr, "\nUDS output contains a flag which provides information about the type of the message.\n"); fprintf(stderr, "\nUDS output contains a flag which provides information about the type of the \n");
fprintf(stderr, "Flags: [SRQ] = Service Request\n"); fprintf(stderr, "message.\n\n");
fprintf(stderr, " [PSR] = Positive Service Response\n"); fprintf(stderr, "Flags:\n");
fprintf(stderr, " [NRC] = Negative Response Code\n"); fprintf(stderr, " [SRQ] = Service Request\n");
fprintf(stderr, " [???] = Unknown (not specified)\n"); fprintf(stderr, " [PSR] = Positive Service Response\n");
fprintf(stderr, " [NRC] = Negative Response Code\n");
fprintf(stderr, " [???] = Unknown (not specified)\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }

View File

@ -65,11 +65,13 @@
void print_usage(char *prg) void print_usage(char *prg)
{ {
fprintf(stderr, "%s - ISO15765-2 protocol performance visualisation.\n", prg);
fprintf(stderr, "\nUsage: %s [options] <CAN interface>\n", prg); fprintf(stderr, "\nUsage: %s [options] <CAN interface>\n", prg);
fprintf(stderr, "Options: -s <can_id> (source can_id. Use 8 digits for extended IDs)\n"); fprintf(stderr, "Options:\n");
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n"); fprintf(stderr, " -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
fprintf(stderr, " -x <addr> (extended addressing mode)\n"); fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
fprintf(stderr, " -X <addr> (extended addressing mode (rx addr))\n"); fprintf(stderr, " -x <addr> (extended addressing mode)\n");
fprintf(stderr, " -X <addr> (extended addressing mode (rx addr))\n");
fprintf(stderr, "\nCAN IDs and addresses are given and expected in hexadecimal values.\n"); fprintf(stderr, "\nCAN IDs and addresses are given and expected in hexadecimal values.\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
@ -363,7 +365,7 @@ int main(int argc, char **argv)
percent = 100; percent = 100;
for (i=0; i < NUMBAR; i++){ for (i=0; i < NUMBAR; i++){
if (i < percent/PERCENTRES) if (i < (int)(percent/PERCENTRES))
printf("X"); printf("X");
else else
printf("."); printf(".");

View File

@ -62,17 +62,18 @@
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, "Options: -s <can_id> (source can_id. Use 8 digits for extended IDs)\n"); fprintf(stderr, "Options:\n");
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n"); fprintf(stderr, " -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
fprintf(stderr, " -x <addr>[:<rxaddr>] (extended addressing / opt. separate rxaddr)\n"); fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
fprintf(stderr, " -p [tx]:[rx] (set and enable tx/rx padding bytes)\n"); fprintf(stderr, " -x <addr>[:<rxaddr>] (extended addressing / opt. separate rxaddr)\n");
fprintf(stderr, " -P <mode> (check rx padding for (l)ength (c)ontent (a)ll)\n"); fprintf(stderr, " -p [tx]:[rx] (set and enable tx/rx padding bytes)\n");
fprintf(stderr, " -b <bs> (blocksize. 0 = off)\n"); fprintf(stderr, " -P <mode> (check rx padding for (l)ength (c)ontent (a)ll)\n");
fprintf(stderr, " -m <val> (STmin in ms/ns. See spec.)\n"); fprintf(stderr, " -b <bs> (blocksize. 0 = off)\n");
fprintf(stderr, " -f <time ns> (force rx stmin value in nanosecs)\n"); fprintf(stderr, " -m <val> (STmin in ms/ns. See spec.)\n");
fprintf(stderr, " -w <num> (max. wait frame transmissions.)\n"); fprintf(stderr, " -f <time ns> (force rx stmin value in nanosecs)\n");
fprintf(stderr, " -l (loop: do not exit after pdu reception.)\n"); fprintf(stderr, " -w <num> (max. wait frame transmissions.)\n");
fprintf(stderr, " -L <mtu>:<tx_dl>:<tx_flags> (link layer options for CAN FD)\n"); fprintf(stderr, " -l (loop: do not exit after pdu reception.)\n");
fprintf(stderr, " -L <mtu>:<tx_dl>:<tx_flags> (link layer options for CAN FD)\n");
fprintf(stderr, "\nCAN IDs and addresses are given and expected in hexadecimal values.\n"); fprintf(stderr, "\nCAN IDs and addresses are given and expected in hexadecimal values.\n");
fprintf(stderr, "The pdu data is written on STDOUT in space separated ASCII hex values.\n"); fprintf(stderr, "The pdu data is written on STDOUT in space separated ASCII hex values.\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");

View File

@ -62,15 +62,16 @@
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, "Options: -s <can_id> (source can_id. Use 8 digits for extended IDs)\n"); fprintf(stderr, "Options:\n");
fprintf(stderr, " -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n"); fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
fprintf(stderr, " -x <addr>[:<rxaddr>] (extended addressing / opt. separate rxaddr)\n"); fprintf(stderr, " -x <addr>[:<rxaddr>] (extended addressing / opt. separate rxaddr)\n");
fprintf(stderr, " -p [tx]:[rx] (set and enable tx/rx padding bytes)\n"); fprintf(stderr, " -p [tx]:[rx] (set and enable tx/rx padding bytes)\n");
fprintf(stderr, " -P <mode> (check rx padding for (l)ength (c)ontent (a)ll)\n"); fprintf(stderr, " -P <mode> (check rx padding for (l)ength (c)ontent (a)ll)\n");
fprintf(stderr, " -t <time ns> (frame transmit time (N_As) in nanosecs)\n"); fprintf(stderr, " -t <time ns> (frame transmit time (N_As) in nanosecs)\n");
fprintf(stderr, " -f <time ns> (ignore FC and force local tx stmin value in nanosecs)\n"); fprintf(stderr, " -f <time ns> (ignore FC and force local tx stmin value in nanosecs)\n");
fprintf(stderr, " -D <len> (send a fixed PDU with len bytes - no STDIN data)\n"); fprintf(stderr, " -D <len> (send a fixed PDU with len bytes - no STDIN data)\n");
fprintf(stderr, " -L <mtu>:<tx_dl>:<tx_flags> (link layer options for CAN FD)\n"); fprintf(stderr, " -L <mtu>:<tx_dl>:<tx_flags> (link layer options for CAN FD)\n");
fprintf(stderr, "\nCAN IDs and addresses are given and expected in hexadecimal values.\n"); fprintf(stderr, "\nCAN IDs and addresses are given and expected in hexadecimal values.\n");
fprintf(stderr, "The pdu data is expected on STDIN in space separated ASCII hex values.\n"); fprintf(stderr, "The pdu data is expected on STDIN in space separated ASCII hex values.\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");

View File

@ -100,28 +100,29 @@ void childdied(int i)
void print_usage(char *prg) void print_usage(char *prg)
{ {
fprintf(stderr, "\nUsage: %s -l <port> -s <can_id> -d <can_id> [options] <CAN interface>\n", prg); fprintf(stderr, "\nUsage: %s -l <port> -s <can_id> -d <can_id> [options] <CAN interface>\n", prg);
fprintf(stderr, "Options: (* = mandatory)\n"); fprintf(stderr, "Options:\n");
fprintf(stderr, "\n");
fprintf(stderr, "ip addressing:\n"); fprintf(stderr, "ip addressing:\n");
fprintf(stderr, " * -l <port> (local port for the server)\n"); fprintf(stderr, " -l <port> * (local port for the server)\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "isotp addressing:\n"); fprintf(stderr, "isotp addressing:\n");
fprintf(stderr, " * -s <can_id> (source can_id. Use 8 digits for extended IDs)\n"); fprintf(stderr, " -s <can_id> * (source can_id. Use 8 digits for extended IDs)\n");
fprintf(stderr, " * -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n"); fprintf(stderr, " -d <can_id> * (destination can_id. Use 8 digits for extended IDs)\n");
fprintf(stderr, " -x <addr>[:<rxaddr>] (extended addressing / opt. separate rxaddr)\n"); fprintf(stderr, " -x <addr>[:<rxaddr>] (extended addressing / opt. separate rxaddr)\n");
fprintf(stderr, " -L <mtu>:<tx_dl>:<tx_flags> (link layer options for CAN FD)\n"); fprintf(stderr, " -L <mtu>:<tx_dl>:<tx_flags> (link layer options for CAN FD)\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "padding:\n"); fprintf(stderr, "padding:\n");
fprintf(stderr, " -p [tx]:[rx] (set and enable tx/rx padding bytes)\n"); fprintf(stderr, " -p [tx]:[rx] (set and enable tx/rx padding bytes)\n");
fprintf(stderr, " -P <mode> (check rx padding for (l)ength (c)ontent (a)ll)\n"); fprintf(stderr, " -P <mode> (check rx padding for (l)ength (c)ontent (a)ll)\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "rx path: (config, which is sent to the sender / data source)\n"); fprintf(stderr, "rx path:\n (config, which is sent to the sender / data source)\n");
fprintf(stderr, " -b <bs> (blocksize. 0 = off)\n"); fprintf(stderr, " -b <bs> (blocksize. 0 = off)\n");
fprintf(stderr, " -m <val> (STmin in ms/ns. See spec.)\n"); fprintf(stderr, " -m <val> (STmin in ms/ns. See spec.)\n");
fprintf(stderr, " -w <num> (max. wait frame transmissions)\n"); fprintf(stderr, " -w <num> (max. wait frame transmissions)\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "tx path: (config, which changes local tx settings)\n"); fprintf(stderr, "tx path:\n (config, which changes local tx settings)\n");
fprintf(stderr, " -t <time ns> (transmit time in nanosecs)\n"); fprintf(stderr, " -t <time ns> (transmit time in nanosecs)\n");
fprintf(stderr, "\n");
fprintf(stderr, "(* = mandatory option)\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "All values except for '-l' and '-t' are expected in hexadecimal values.\n"); fprintf(stderr, "All values except for '-l' and '-t' are expected in hexadecimal values.\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");

View File

@ -69,14 +69,15 @@
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, "Options: -s <can_id> (source can_id. Use 8 digits for extended IDs)\n"); fprintf(stderr, "Options:\n");
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n"); fprintf(stderr, " -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
fprintf(stderr, " -x <addr> (extended addressing mode)\n"); fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
fprintf(stderr, " -X <addr> (extended addressing mode - rx addr)\n"); fprintf(stderr, " -x <addr> (extended addressing mode)\n");
fprintf(stderr, " -c (color mode)\n"); fprintf(stderr, " -X <addr> (extended addressing mode - rx addr)\n");
fprintf(stderr, " -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n"); fprintf(stderr, " -c (color mode)\n");
fprintf(stderr, " -f <format> (1 = HEX, 2 = ASCII, 3 = HEX & ASCII - default: %d)\n", FORMAT_DEFAULT); fprintf(stderr, " -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n");
fprintf(stderr, " -L <mtu>:<tx_dl>:<tx_flags> (link layer options for CAN FD)\n"); fprintf(stderr, " -f <format> (1 = HEX, 2 = ASCII, 3 = HEX & ASCII - default: %d)\n", FORMAT_DEFAULT);
fprintf(stderr, " -L <mtu>:<tx_dl>:<tx_flags> (link layer options for CAN FD)\n");
fprintf(stderr, " -h <len> (head: print only first <len> bytes)\n"); fprintf(stderr, " -h <len> (head: print only first <len> bytes)\n");
fprintf(stderr, "\nCAN IDs and addresses are given and expected in hexadecimal values.\n"); fprintf(stderr, "\nCAN IDs and addresses are given and expected in hexadecimal values.\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");

View File

@ -102,23 +102,25 @@ void perror_syslog(const char *s)
void print_usage(char *prg) void print_usage(char *prg)
{ {
fprintf(stderr, "%s - IP over CAN ISO-TP (ISO15765-2) tunnel / proof-of-concept.\n", prg);
fprintf(stderr, "\nUsage: %s [options] <CAN interface>\n\n", prg); fprintf(stderr, "\nUsage: %s [options] <CAN interface>\n\n", prg);
fprintf(stderr, "This program creates a Linux tunnel netdevice 'ctunX' and transfers the\n"); fprintf(stderr, "This program creates a Linux tunnel netdevice 'ctunX' and transfers the\n");
fprintf(stderr, "ethernet frames inside ISO15765-2 (unreliable) datagrams on CAN.\n\n"); fprintf(stderr, "ethernet frames inside ISO15765-2 (unreliable) datagrams on CAN.\n\n");
fprintf(stderr, "Options: -s <can_id> (source can_id. Use 8 digits for extended IDs)\n"); fprintf(stderr, "Options:\n");
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n"); fprintf(stderr, " -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
fprintf(stderr, " -n <name> (name of created IP netdevice. Default: '%s')\n", DEFAULT_NAME); fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
fprintf(stderr, " -x <addr>[:<rxaddr>] (extended addressing / opt. separate rxaddr)\n"); fprintf(stderr, " -n <name> (name of created IP netdevice. Default: '%s')\n", DEFAULT_NAME);
fprintf(stderr, " -L <mtu>:<tx_dl>:<tx_flags> (link layer options for CAN FD)\n"); fprintf(stderr, " -x <addr>[:<rxaddr>] (extended addressing / opt. separate rxaddr)\n");
fprintf(stderr, " -p [tx]:[rx] (set and enable tx/rx padding bytes)\n"); fprintf(stderr, " -L <mtu>:<tx_dl>:<tx_flags> (link layer options for CAN FD)\n");
fprintf(stderr, " -P <mode> (check rx padding for (l)ength (c)ontent (a)ll)\n"); fprintf(stderr, " -p [tx]:[rx] (set and enable tx/rx padding bytes)\n");
fprintf(stderr, " -t <time ns> (transmit time in nanosecs)\n"); fprintf(stderr, " -P <mode> (check rx padding for (l)ength (c)ontent (a)ll)\n");
fprintf(stderr, " -b <bs> (blocksize. 0 = off)\n"); fprintf(stderr, " -t <time ns> (transmit time in nanosecs)\n");
fprintf(stderr, " -m <val> (STmin in ms/ns. See spec.)\n"); fprintf(stderr, " -b <bs> (blocksize. 0 = off)\n");
fprintf(stderr, " -w <num> (max. wait frame transmissions.)\n"); fprintf(stderr, " -m <val> (STmin in ms/ns. See spec.)\n");
fprintf(stderr, " -D (daemonize to background when tun device created)\n"); fprintf(stderr, " -w <num> (max. wait frame transmissions.)\n");
fprintf(stderr, " -h (half duplex mode.)\n"); fprintf(stderr, " -D (daemonize to background when tun device created)\n");
fprintf(stderr, " -v (verbose mode. Print symbols for tunneled msgs.)\n"); fprintf(stderr, " -h (half duplex mode.)\n");
fprintf(stderr, " -v (verbose mode. Print symbols for tunneled msgs.)\n");
fprintf(stderr, "\nCAN IDs and addresses are given and expected in hexadecimal values.\n"); fprintf(stderr, "\nCAN IDs and addresses are given and expected in hexadecimal values.\n");
fprintf(stderr, "Use e.g. 'ifconfig ctun0 123.123.123.1 pointopoint 123.123.123.2 up'\n"); fprintf(stderr, "Use e.g. 'ifconfig ctun0 123.123.123.1 pointopoint 123.123.123.2 up'\n");
fprintf(stderr, "to create a point-to-point IP connection on CAN.\n"); fprintf(stderr, "to create a point-to-point IP connection on CAN.\n");

View File

@ -30,9 +30,9 @@
#include "libj1939.h" #include "libj1939.h"
static const char help_msg[] = static const char help_msg[] =
"jacd: An SAE J1939 address claiming daemon" "\n" "j1939acd: An SAE J1939 address claiming daemon" "\n"
"Usage: jacd [options] NAME [INTF]" "\n" "Usage: j1939acd [options] NAME [INTF]" "\n"
"\n" "Options:\n"
" -v, --verbose Increase verbosity" "\n" " -v, --verbose Increase verbosity" "\n"
" -r, --range=RANGE Ranges of source addresses" "\n" " -r, --range=RANGE Ranges of source addresses" "\n"
" e.g. 80,50-100,200-210 (defaults to 0-253)" "\n" " e.g. 80,50-100,200-210 (defaults to 0-253)" "\n"
@ -43,7 +43,9 @@ static const char help_msg[] =
"NAME is the 64bit nodename" "\n" "NAME is the 64bit nodename" "\n"
"\n" "\n"
"Example:" "\n" "Example:" "\n"
"jacd -r 100,80-120 -c /tmp/1122334455667788.jacd 1122334455667788" "\n" "j1939acd -r 100,80-120 -c /tmp/1122334455667788.jacd 1122334455667788" "\n"
"Examples:" "\n"
"j1939acd -r 100,80-120 -c /tmp/1122334455667788.jacd 1122334455667788" "\n"
; ;
#ifdef _GNU_SOURCE #ifdef _GNU_SOURCE
@ -182,7 +184,7 @@ static const struct j1939_filter filt[] = {
.pgn = J1939_PGN_REQUEST, .pgn = J1939_PGN_REQUEST,
.pgn_mask = J1939_PGN_PDU1_MAX, .pgn_mask = J1939_PGN_PDU1_MAX,
}, { }, {
.pgn = 0x0fed8, .pgn = J1939_PGN_ADDRESS_COMMANDED,
.pgn_mask = J1939_PGN_MAX, .pgn_mask = J1939_PGN_MAX,
}, },
}; };
@ -198,7 +200,7 @@ static int open_socket(const char *device, uint64_t name)
.addr = J1939_IDLE_ADDR, .addr = J1939_IDLE_ADDR,
.pgn = J1939_NO_PGN, .pgn = J1939_NO_PGN,
}, },
.can_ifindex = if_nametoindex(s.intf), .can_ifindex = if_nametoindex(device),
}; };
if (s.verbose) if (s.verbose)
@ -251,7 +253,7 @@ static int repeat_address(int sock, uint64_t name)
ret = sendto(sock, dat, sizeof(dat), 0, (const struct sockaddr *)&saddr, ret = sendto(sock, dat, sizeof(dat), 0, (const struct sockaddr *)&saddr,
sizeof(saddr)); sizeof(saddr));
if (must_warn(ret)) if (must_warn(ret))
err(1, "send address claim for 0x%02x", s.last_sa); fprintf(stderr, "send address claim for 0x%02x\n", s.last_sa);
return ret; return ret;
} }
static int claim_address(int sock, uint64_t name, int sa) static int claim_address(int sock, uint64_t name, int sa)
@ -290,7 +292,7 @@ static int request_addresses(int sock)
fprintf(stderr, "- sendto(, { 0, 0xee, 0, }, %zi, 0, %s, %zi);\n", sizeof(dat), libj1939_addr2str(&saddr), sizeof(saddr)); fprintf(stderr, "- sendto(, { 0, 0xee, 0, }, %zi, 0, %s, %zi);\n", sizeof(dat), libj1939_addr2str(&saddr), sizeof(saddr));
ret = sendto(sock, dat, sizeof(dat), 0, (void *)&saddr, sizeof(saddr)); ret = sendto(sock, dat, sizeof(dat), 0, (void *)&saddr, sizeof(saddr));
if (must_warn(ret)) if (must_warn(ret))
err(1, "send request for address claims"); fprintf(stdout, "send request for address claims");
return ret; return ret;
} }
@ -512,12 +514,12 @@ int main(int argc, char *argv[])
if ((s.current_sa < J1939_IDLE_ADDR) && !(addr[s.current_sa].flags & F_USE)) { if ((s.current_sa < J1939_IDLE_ADDR) && !(addr[s.current_sa].flags & F_USE)) {
if (s.verbose) if (s.verbose)
err(0, "forget saved address 0x%02x", s.current_sa); fprintf(stderr, "- forget saved address 0x%02x\n", s.current_sa);
s.current_sa = J1939_IDLE_ADDR; s.current_sa = J1939_IDLE_ADDR;
} }
if (s.verbose) if (s.verbose)
err(0, "ready for %s:%016llx", s.intf, (long long)s.name); fprintf(stderr, "- ready for %s:%016llx\n", s.intf, (long long)s.name);
if (!s.intf || !s.name) if (!s.intf || !s.name)
err(1, "bad arguments"); err(1, "bad arguments");
ret = sock = open_socket(s.intf, s.name); ret = sock = open_socket(s.intf, s.name);
@ -581,7 +583,7 @@ int main(int argc, char *argv[])
break; break;
if (s.state == STATE_REQ_SENT) { if (s.state == STATE_REQ_SENT) {
if (s.verbose) if (s.verbose)
err(0, "request sent, pending for 1250 ms"); fprintf(stderr, "- request sent, pending for 1250 ms\n");
schedule_itimer(1250); schedule_itimer(1250);
s.state = STATE_REQ_PENDING; s.state = STATE_REQ_PENDING;
} else if (s.state == STATE_OPERATIONAL) { } else if (s.state == STATE_OPERATIONAL) {
@ -611,14 +613,14 @@ int main(int argc, char *argv[])
/* ourselves, disable itimer */ /* ourselves, disable itimer */
s.current_sa = sa; s.current_sa = sa;
if (s.verbose) if (s.verbose)
err(0, "claimed 0x%02x", sa); fprintf(stderr, "- claimed 0x%02x\n", sa);
} else if (sa == s.current_sa) { } else if (sa == s.current_sa) {
if (s.verbose) if (s.verbose)
err(0, "address collision for 0x%02x", sa); fprintf(stderr, "- address collision for 0x%02x\n", sa);
if (s.name > saddr.can_addr.j1939.name) { if (s.name > saddr.can_addr.j1939.name) {
sa = choose_new_sa(s.name, sa); sa = choose_new_sa(s.name, sa);
if (sa == J1939_IDLE_ADDR) { if (sa == J1939_IDLE_ADDR) {
err(0, "no address left"); fprintf(stdout, "no address left");
/* put J1939_IDLE_ADDR in cache file */ /* put J1939_IDLE_ADDR in cache file */
s.current_sa = sa; s.current_sa = sa;
goto done; goto done;
@ -629,7 +631,7 @@ int main(int argc, char *argv[])
schedule_itimer(50); schedule_itimer(50);
} }
break; break;
case 0x0fed8: case J1939_PGN_ADDRESS_COMMANDED:
if (!host_is_little_endian()) if (!host_is_little_endian())
bswap(dat, 8); bswap(dat, 8);
memcpy(&cmd_name, dat, 8); memcpy(&cmd_name, dat, 8);
@ -643,7 +645,7 @@ int main(int argc, char *argv[])
} }
done: done:
if (s.verbose) if (s.verbose)
err(0, "shutdown"); fprintf(stderr, "- shutdown\n");
claim_address(sock, s.name, J1939_IDLE_ADDR); claim_address(sock, s.name, J1939_IDLE_ADDR);
save_cache(); save_cache();
return 0; return 0;

View File

@ -36,13 +36,13 @@
_min1 < _min2 ? _min1 : _min2; }) _min1 < _min2 ? _min1 : _min2; })
struct jcat_stats { struct j1939cat_stats {
int err; int err;
uint32_t tskey; uint32_t tskey;
uint32_t send; uint32_t send;
}; };
struct jcat_priv { struct j1939cat_priv {
int sock; int sock;
int infile; int infile;
int outfile; int outfile;
@ -63,12 +63,12 @@ struct jcat_priv {
struct sock_extended_err *serr; struct sock_extended_err *serr;
struct scm_timestamping *tss; struct scm_timestamping *tss;
struct jcat_stats stats; struct j1939cat_stats stats;
}; };
static const char help_msg[] = static const char help_msg[] =
"jcat: netcat tool for j1939\n" "j1939cat: netcat-like tool for j1939\n"
"Usage: jcat FROM TO\n" "Usage: j1939cat [options] FROM TO\n"
" FROM / TO - or [IFACE][:[SA][,[PGN][,NAME]]]\n" " FROM / TO - or [IFACE][:[SA][,[PGN][,NAME]]]\n"
"Options:\n" "Options:\n"
" -i <infile> (default stdin)\n" " -i <infile> (default stdin)\n"
@ -79,15 +79,15 @@ static const char help_msg[] =
" -R <count> Set send repeat count. Default: 1\n" " -R <count> Set send repeat count. Default: 1\n"
"\n" "\n"
"Example:\n" "Example:\n"
"jcat -i some_file_to_send can0:0x80 :0x90,0x12300\n" "j1939cat -i some_file_to_send can0:0x80 :0x90,0x12300\n"
"jcat can0:0x90 -r > /tmp/some_file_to_receive\n" "j1939cat can0:0x90 -r > /tmp/some_file_to_receive\n"
"\n" "\n"
; ;
static const char optstring[] = "?i:vs:rp:P:R:"; static const char optstring[] = "?hi:vs:rp:P:R:";
static void jcat_init_sockaddr_can(struct sockaddr_can *sac) static void j1939cat_init_sockaddr_can(struct sockaddr_can *sac)
{ {
sac->can_family = AF_CAN; sac->can_family = AF_CAN;
sac->can_addr.j1939.addr = J1939_NO_ADDR; sac->can_addr.j1939.addr = J1939_NO_ADDR;
@ -95,7 +95,7 @@ static void jcat_init_sockaddr_can(struct sockaddr_can *sac)
sac->can_addr.j1939.pgn = J1939_NO_PGN; sac->can_addr.j1939.pgn = J1939_NO_PGN;
} }
static ssize_t jcat_send_one(struct jcat_priv *priv, int out_fd, static ssize_t j1939cat_send_one(struct j1939cat_priv *priv, int out_fd,
const void *buf, size_t buf_size) const void *buf, size_t buf_size)
{ {
ssize_t num_sent; ssize_t num_sent;
@ -121,7 +121,7 @@ static ssize_t jcat_send_one(struct jcat_priv *priv, int out_fd,
return -EINVAL; return -EINVAL;
} }
if (num_sent > buf_size) /* Should never happen */ { if (num_sent > (ssize_t)buf_size) /* Should never happen */ {
warn("%s: send more then read", __func__); warn("%s: send more then read", __func__);
return -EINVAL; return -EINVAL;
} }
@ -129,10 +129,10 @@ static ssize_t jcat_send_one(struct jcat_priv *priv, int out_fd,
return num_sent; return num_sent;
} }
static void jcat_print_timestamp(struct jcat_priv *priv, const char *name, static void j1939cat_print_timestamp(struct j1939cat_priv *priv, const char *name,
struct timespec *cur) struct timespec *cur)
{ {
struct jcat_stats *stats = &priv->stats; struct j1939cat_stats *stats = &priv->stats;
if (!(cur->tv_sec | cur->tv_nsec)) if (!(cur->tv_sec | cur->tv_nsec))
return; return;
@ -144,7 +144,7 @@ static void jcat_print_timestamp(struct jcat_priv *priv, const char *name,
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
static const char *jcat_tstype_to_str(int tstype) static const char *j1939cat_tstype_to_str(int tstype)
{ {
switch (tstype) { switch (tstype) {
case SCM_TSTAMP_SCHED: case SCM_TSTAMP_SCHED:
@ -159,17 +159,17 @@ static const char *jcat_tstype_to_str(int tstype)
} }
/* Check the stats of SCM_TIMESTAMPING_OPT_STATS */ /* Check the stats of SCM_TIMESTAMPING_OPT_STATS */
static void jcat_scm_opt_stats(struct jcat_priv *priv, void *buf, int len) static void j1939cat_scm_opt_stats(struct j1939cat_priv *priv, void *buf, int len)
{ {
struct jcat_stats *stats = &priv->stats; struct j1939cat_stats *stats = &priv->stats;
int offset = 0; int offset = 0;
while (offset < len) { while (offset < len) {
struct nlattr *nla = (struct nlattr *) (buf + offset); struct nlattr *nla = (struct nlattr *) ((char *)buf + offset);
switch (nla->nla_type) { switch (nla->nla_type) {
case J1939_NLA_BYTES_ACKED: case J1939_NLA_BYTES_ACKED:
stats->send = *(uint32_t *)((void *)nla + NLA_HDRLEN); stats->send = *(uint32_t *)((char *)nla + NLA_HDRLEN);
break; break;
default: default:
warnx("not supported J1939_NLA field\n"); warnx("not supported J1939_NLA field\n");
@ -179,9 +179,9 @@ static void jcat_scm_opt_stats(struct jcat_priv *priv, void *buf, int len)
} }
} }
static int jcat_extract_serr(struct jcat_priv *priv) static int j1939cat_extract_serr(struct j1939cat_priv *priv)
{ {
struct jcat_stats *stats = &priv->stats; struct j1939cat_stats *stats = &priv->stats;
struct sock_extended_err *serr = priv->serr; struct sock_extended_err *serr = priv->serr;
struct scm_timestamping *tss = priv->tss; struct scm_timestamping *tss = priv->tss;
@ -205,7 +205,7 @@ static int jcat_extract_serr(struct jcat_priv *priv)
serr->ee_errno); serr->ee_errno);
stats->tskey = serr->ee_data; stats->tskey = serr->ee_data;
jcat_print_timestamp(priv, jcat_tstype_to_str(serr->ee_info), j1939cat_print_timestamp(priv, j1939cat_tstype_to_str(serr->ee_info),
&tss->ts[0]); &tss->ts[0]);
if (serr->ee_info == SCM_TSTAMP_SCHED) if (serr->ee_info == SCM_TSTAMP_SCHED)
@ -232,7 +232,7 @@ static int jcat_extract_serr(struct jcat_priv *priv)
warnx("serr: unknown ee_info: %i", warnx("serr: unknown ee_info: %i",
serr->ee_info); serr->ee_info);
jcat_print_timestamp(priv, " ABT", &tss->ts[0]); j1939cat_print_timestamp(priv, " ABT", &tss->ts[0]);
warnx("serr: tx error: %i, %s", serr->ee_errno, strerror(serr->ee_errno)); warnx("serr: tx error: %i, %s", serr->ee_errno, strerror(serr->ee_errno));
return serr->ee_errno; return serr->ee_errno;
@ -243,7 +243,7 @@ static int jcat_extract_serr(struct jcat_priv *priv)
return 0; return 0;
} }
static int jcat_parse_cm(struct jcat_priv *priv, struct cmsghdr *cm) static int j1939cat_parse_cm(struct j1939cat_priv *priv, struct cmsghdr *cm)
{ {
const size_t hdr_len = CMSG_ALIGN(sizeof(struct cmsghdr)); const size_t hdr_len = CMSG_ALIGN(sizeof(struct cmsghdr));
@ -253,7 +253,7 @@ static int jcat_parse_cm(struct jcat_priv *priv, struct cmsghdr *cm)
void *jstats = (void *)CMSG_DATA(cm); void *jstats = (void *)CMSG_DATA(cm);
/* Activated with SOF_TIMESTAMPING_OPT_STATS */ /* Activated with SOF_TIMESTAMPING_OPT_STATS */
jcat_scm_opt_stats(priv, jstats, cm->cmsg_len - hdr_len); j1939cat_scm_opt_stats(priv, jstats, cm->cmsg_len - hdr_len);
} else if (cm->cmsg_level == SOL_CAN_J1939 && } else if (cm->cmsg_level == SOL_CAN_J1939 &&
cm->cmsg_type == SCM_J1939_ERRQUEUE) { cm->cmsg_type == SCM_J1939_ERRQUEUE) {
priv->serr = (void *)CMSG_DATA(cm); priv->serr = (void *)CMSG_DATA(cm);
@ -264,7 +264,7 @@ static int jcat_parse_cm(struct jcat_priv *priv, struct cmsghdr *cm)
return 0; return 0;
} }
static int jcat_recv_err(struct jcat_priv *priv) static int j1939cat_recv_err(struct j1939cat_priv *priv)
{ {
char control[100]; char control[100];
struct cmsghdr *cm; struct cmsghdr *cm;
@ -285,18 +285,18 @@ static int jcat_recv_err(struct jcat_priv *priv)
for (cm = CMSG_FIRSTHDR(&msg); cm && cm->cmsg_len; for (cm = CMSG_FIRSTHDR(&msg); cm && cm->cmsg_len;
cm = CMSG_NXTHDR(&msg, cm)) { cm = CMSG_NXTHDR(&msg, cm)) {
jcat_parse_cm(priv, cm); j1939cat_parse_cm(priv, cm);
if (priv->serr && priv->tss) if (priv->serr && priv->tss)
return jcat_extract_serr(priv); return j1939cat_extract_serr(priv);
} }
return 0; return 0;
} }
static int jcat_send_loop(struct jcat_priv *priv, int out_fd, char *buf, static int j1939cat_send_loop(struct j1939cat_priv *priv, int out_fd, char *buf,
size_t buf_size) size_t buf_size)
{ {
struct jcat_stats *stats = &priv->stats; struct j1939cat_stats *stats = &priv->stats;
ssize_t count; ssize_t count;
char *tmp_buf = buf; char *tmp_buf = buf;
unsigned int events = POLLOUT | POLLERR; unsigned int events = POLLOUT | POLLERR;
@ -328,7 +328,7 @@ static int jcat_send_loop(struct jcat_priv *priv, int out_fd, char *buf,
} }
if (fds.revents & POLLERR) { if (fds.revents & POLLERR) {
ret = jcat_recv_err(priv); ret = j1939cat_recv_err(priv);
if (ret == -EINTR) if (ret == -EINTR)
continue; continue;
else if (ret) else if (ret)
@ -339,12 +339,12 @@ static int jcat_send_loop(struct jcat_priv *priv, int out_fd, char *buf,
} }
if (fds.revents & POLLOUT) { if (fds.revents & POLLOUT) {
num_sent = jcat_send_one(priv, out_fd, tmp_buf, count); num_sent = j1939cat_send_one(priv, out_fd, tmp_buf, count);
if (num_sent < 0) if (num_sent < 0)
return num_sent; return num_sent;
} }
} else { } else {
num_sent = jcat_send_one(priv, out_fd, tmp_buf, count); num_sent = j1939cat_send_one(priv, out_fd, tmp_buf, count);
if (num_sent < 0) if (num_sent < 0)
return num_sent; return num_sent;
} }
@ -366,13 +366,14 @@ static int jcat_send_loop(struct jcat_priv *priv, int out_fd, char *buf,
return 0; return 0;
} }
static int jcat_sendfile(struct jcat_priv *priv, int out_fd, int in_fd, static int j1939cat_sendfile(struct j1939cat_priv *priv, int out_fd, int in_fd,
off_t *offset, size_t count) off_t *offset, size_t count)
{ {
int ret = EXIT_SUCCESS; int ret = EXIT_SUCCESS;
off_t orig = 0; off_t orig = 0;
char *buf; char *buf;
size_t to_read, num_read, buf_size; ssize_t num_read;
size_t to_read, buf_size;
buf_size = min(priv->max_transfer, count); buf_size = min(priv->max_transfer, count);
buf = malloc(buf_size); buf = malloc(buf_size);
@ -408,7 +409,7 @@ static int jcat_sendfile(struct jcat_priv *priv, int out_fd, int in_fd,
if (num_read == 0) if (num_read == 0)
break; /* EOF */ break; /* EOF */
ret = jcat_send_loop(priv, out_fd, buf, num_read); ret = j1939cat_send_loop(priv, out_fd, buf, num_read);
if (ret) if (ret)
goto do_free; goto do_free;
@ -437,7 +438,7 @@ do_nofree:
return ret; return ret;
} }
static size_t jcat_get_file_size(int fd) static size_t j1939cat_get_file_size(int fd)
{ {
off_t offset; off_t offset;
@ -451,20 +452,21 @@ static size_t jcat_get_file_size(int fd)
return offset; return offset;
} }
static int jcat_send(struct jcat_priv *priv) static int j1939cat_send(struct j1939cat_priv *priv)
{ {
unsigned int size = 0; unsigned int size = 0;
int ret, i; unsigned int i;
int ret;
if (priv->todo_filesize) if (priv->todo_filesize)
size = jcat_get_file_size(priv->infile); size = j1939cat_get_file_size(priv->infile);
if (!size) if (!size)
return EXIT_FAILURE; return EXIT_FAILURE;
for (i = 0; i < priv->repeat; i++) { for (i = 0; i < priv->repeat; i++) {
priv->round++; priv->round++;
ret = jcat_sendfile(priv, priv->sock, priv->infile, NULL, size); ret = j1939cat_sendfile(priv, priv->sock, priv->infile, NULL, size);
if (ret) if (ret)
break; break;
@ -475,7 +477,7 @@ static int jcat_send(struct jcat_priv *priv)
return ret; return ret;
} }
static int jcat_recv_one(struct jcat_priv *priv, uint8_t *buf, size_t buf_size) static int j1939cat_recv_one(struct j1939cat_priv *priv, uint8_t *buf, size_t buf_size)
{ {
int ret; int ret;
@ -494,7 +496,7 @@ static int jcat_recv_one(struct jcat_priv *priv, uint8_t *buf, size_t buf_size)
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
static int jcat_recv(struct jcat_priv *priv) static int j1939cat_recv(struct j1939cat_priv *priv)
{ {
int ret = EXIT_SUCCESS; int ret = EXIT_SUCCESS;
size_t buf_size; size_t buf_size;
@ -508,7 +510,7 @@ static int jcat_recv(struct jcat_priv *priv)
} }
while (priv->todo_recv) { while (priv->todo_recv) {
ret = jcat_recv_one(priv, buf, buf_size); ret = j1939cat_recv_one(priv, buf, buf_size);
if (ret) if (ret)
break; break;
} }
@ -517,7 +519,7 @@ static int jcat_recv(struct jcat_priv *priv)
return ret; return ret;
} }
static int jcat_sock_prepare(struct jcat_priv *priv) static int j1939cat_sock_prepare(struct j1939cat_priv *priv)
{ {
unsigned int sock_opt; unsigned int sock_opt;
int value; int value;
@ -581,7 +583,7 @@ static int jcat_sock_prepare(struct jcat_priv *priv)
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
static int jcat_parse_args(struct jcat_priv *priv, int argc, char *argv[]) static int j1939cat_parse_args(struct j1939cat_priv *priv, int argc, char *argv[])
{ {
int opt; int opt;
@ -617,6 +619,7 @@ static int jcat_parse_args(struct jcat_priv *priv, int argc, char *argv[])
if (priv->repeat < 1) if (priv->repeat < 1)
err(EXIT_FAILURE, "send/repeat count can't be less then 1\n"); err(EXIT_FAILURE, "send/repeat count can't be less then 1\n");
break; break;
case 'h': /*fallthrough*/
default: default:
fputs(help_msg, stderr); fputs(help_msg, stderr);
return EXIT_FAILURE; return EXIT_FAILURE;
@ -641,7 +644,7 @@ static int jcat_parse_args(struct jcat_priv *priv, int argc, char *argv[])
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
struct jcat_priv *priv; struct j1939cat_priv *priv;
int ret; int ret;
priv = malloc(sizeof(*priv)); priv = malloc(sizeof(*priv));
@ -657,21 +660,21 @@ int main(int argc, char *argv[])
priv->polltimeout = 100000; priv->polltimeout = 100000;
priv->repeat = 1; priv->repeat = 1;
jcat_init_sockaddr_can(&priv->sockname); j1939cat_init_sockaddr_can(&priv->sockname);
jcat_init_sockaddr_can(&priv->peername); j1939cat_init_sockaddr_can(&priv->peername);
ret = jcat_parse_args(priv, argc, argv); ret = j1939cat_parse_args(priv, argc, argv);
if (ret) if (ret)
return ret; return ret;
ret = jcat_sock_prepare(priv); ret = j1939cat_sock_prepare(priv);
if (ret) if (ret)
return ret; return ret;
if (priv->todo_recv) if (priv->todo_recv)
ret = jcat_recv(priv); ret = j1939cat_recv(priv);
else else
ret = jcat_send(priv); ret = j1939cat_send(priv);
close(priv->infile); close(priv->infile);
close(priv->outfile); close(priv->outfile);

View File

@ -30,9 +30,9 @@
* getopt * getopt
*/ */
static const char help_msg[] = static const char help_msg[] =
"jspy: An SAE J1939 spy utility" "\n" "j1939spy: An SAE J1939 spy utility" "\n"
"Usage: jspy [OPTION...] [[IFACE:][NAME|SA][,PGN]]" "\n" "Usage: j1939spy [OPTION...] [[IFACE:][NAME|SA][,PGN]]" "\n"
"\n" "Options:\n"
" -v, --verbose Increase verbosity" "\n" " -v, --verbose Increase verbosity" "\n"
" -P, --promisc Run in promiscuous mode" "\n" " -P, --promisc Run in promiscuous mode" "\n"
" (= receive traffic not for this ECU)" "\n" " (= receive traffic not for this ECU)" "\n"
@ -95,8 +95,8 @@ static uint8_t *buf;
*/ */
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int ret, sock, j, opt; int ret, sock, opt;
unsigned int len; unsigned int j, len;
struct timeval tref, tdut, ttmp; struct timeval tref, tdut, ttmp;
struct sockaddr_can src; struct sockaddr_can src;
struct j1939_filter filt; struct j1939_filter filt;
@ -287,7 +287,7 @@ int main(int argc, char **argv)
printf("[%i%s]", len, (msg.msg_flags & MSG_TRUNC) ? "..." : ""); printf("[%i%s]", len, (msg.msg_flags & MSG_TRUNC) ? "..." : "");
for (j = 0; j < len; ) { for (j = 0; j < len; ) {
int end = j + 4; unsigned int end = j + 4;
if (end > len) if (end > len)
end = len; end = len;
printf(" "); printf(" ");

View File

@ -31,9 +31,9 @@
* getopt * getopt
*/ */
static const char help_msg[] = static const char help_msg[] =
"jsr: An SAE J1939 send/recv utility" "\n" "j1939sr: An SAE J1939 send/recv utility" "\n"
"Usage: jsr [OPTION...] SOURCE [DEST]" "\n" "Usage: j1939sr [OPTION...] SOURCE [DEST]" "\n"
"\n" "Options:\n"
" -v, --verbose Increase verbosity" "\n" " -v, --verbose Increase verbosity" "\n"
" -p, --priority=VAL J1939 priority (0..7, default 6)" "\n" " -p, --priority=VAL J1939 priority (0..7, default 6)" "\n"
" -S, --serialize Strictly serialize outgoing packets" "\n" " -S, --serialize Strictly serialize outgoing packets" "\n"

2
lib.c
View File

@ -583,7 +583,7 @@ void snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *c
if (!sep) if (!sep)
sep = defsep; sep = defsep;
for (i = 0; i < ARRAY_SIZE(error_classes); i++) { for (i = 0; i < (int)ARRAY_SIZE(error_classes); i++) {
mask = 1 << i; mask = 1 << i;
if (class & mask) { if (class & mask) {
if (classes) if (classes)

View File

@ -53,7 +53,7 @@ static const char *libj1939_ifnam(int ifindex)
fetch_names(); fetch_names();
for (lp = saved; lp->if_index; ++lp) { for (lp = saved; lp->if_index; ++lp) {
if (lp->if_index == ifindex) if (lp->if_index == (unsigned int)ifindex)
return lp->if_name; return lp->if_name;
} }
if (cached) { if (cached) {

131
log2asc.c
View File

@ -60,24 +60,102 @@ 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, "%s - convert compact CAN frame logfile to ASC logfile.\n", prg);
fprintf(stderr, "Options: -I <infile> (default stdin)\n"); fprintf(stderr, "Usage: %s <options> [can-interfaces]\n", prg);
fprintf(stderr, " -O <outfile> (default stdout)\n"); fprintf(stderr, "Options:\n");
fprintf(stderr, " -4 (reduce decimal place to 4 digits)\n"); fprintf(stderr, " -I <infile> (default stdin)\n");
fprintf(stderr, " -n (set newline to cr/lf - default lf)\n"); fprintf(stderr, " -O <outfile> (default stdout)\n");
fprintf(stderr, " -4 (reduce decimal place to 4 digits)\n");
fprintf(stderr, " -n (set newline to cr/lf - default lf)\n");
fprintf(stderr, " -f (use CANFD format also for Classic CAN)\n");
fprintf(stderr, " -r (supress dlc for RTR frames - pre v8.5 tools)\n");
}
void can_asc(struct canfd_frame *cf, int devno, int nortrdlc, FILE *outfile)
{
int i;
char id[10];
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) {
if (nortrdlc)
fprintf(outfile, "r"); /* RTR frame */
else
fprintf(outfile, "r %d", cf->len); /* RTR frame */
} else {
fprintf(outfile, "d %d", cf->len); /* data frame */
for (i = 0; i < cf->len; i++) {
fprintf(outfile, " %02X", cf->data[i]);
}
}
}
}
void canfd_asc(struct canfd_frame *cf, int devno, int mtu, FILE *outfile)
{
int i;
char id[10];
unsigned int flags = 0;
unsigned int dlen = cf->len;
/* relevant flags in Flags field */
#define ASC_F_RTR 0x00000010
#define ASC_F_FDF 0x00001000
#define ASC_F_BRS 0x00002000
#define ASC_F_ESI 0x00004000
fprintf(outfile, "CANFD %3d Rx ", devno); /* 3 column channel number right aligned */
sprintf(id, "%X%c", cf->can_id & CAN_EFF_MASK,
(cf->can_id & CAN_EFF_FLAG)?'x':' ');
fprintf(outfile, "%11s ", id);
fprintf(outfile, "%c ", (cf->flags & CANFD_BRS)?'1':'0');
fprintf(outfile, "%c ", (cf->flags & CANFD_ESI)?'1':'0');
fprintf(outfile, "%x ", can_len2dlc(dlen));
if (mtu == CAN_MTU) {
if (cf->can_id & CAN_RTR_FLAG) {
/* no data length but dlc for RTR frames */
dlen = 0;
flags = ASC_F_RTR;
}
} else {
flags = ASC_F_FDF;
if (cf->flags & CANFD_BRS)
flags |= ASC_F_BRS;
if (cf->flags & CANFD_ESI)
flags |= ASC_F_ESI;
}
fprintf(outfile, "%2d", dlen);
for (i = 0; i < (int)dlen; i++) {
fprintf(outfile, " %02X", cf->data[i]);
}
fprintf(outfile, " %8d %4d %8X 0 0 0 0 0", 130000, 130, flags);
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
static char buf[BUFSZ], device[BUFSZ], ascframe[BUFSZ], id[10]; static char buf[BUFSZ], device[BUFSZ], ascframe[BUFSZ];
struct canfd_frame cf; struct canfd_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, fdfmt, nortrdlc, d4, opt, mtu;
while ((opt = getopt(argc, argv, "I:O:4n?")) != -1) { while ((opt = getopt(argc, argv, "I:O:4nfr?")) != -1) {
switch (opt) { switch (opt) {
case 'I': case 'I':
infile = fopen(optarg, "r"); infile = fopen(optarg, "r");
@ -99,6 +177,14 @@ int main(int argc, char **argv)
crlf = 1; crlf = 1;
break; break;
case 'f':
fdfmt = 1;
break;
case 'r':
nortrdlc = 1;
break;
case '4': case '4':
d4 = 1; d4 = 1;
break; break;
@ -160,9 +246,14 @@ int main(int argc, char **argv)
} }
if (devno) { /* only convert for selected CAN devices */ if (devno) { /* only convert for selected CAN devices */
if (parse_canframe(ascframe, &cf) != CAN_MTU) /* no CAN FD support so far */ mtu = parse_canframe(ascframe, &cf);
if ((mtu != CAN_MTU) && (mtu != CANFD_MTU))
return 1; return 1;
/* we don't support error message frames in CAN FD */
if ((mtu == CANFD_MTU) && (cf.can_id & CAN_ERR_FLAG))
continue;
tv.tv_sec = tv.tv_sec - start_tv.tv_sec; tv.tv_sec = tv.tv_sec - start_tv.tv_sec;
tv.tv_usec = tv.tv_usec - start_tv.tv_usec; tv.tv_usec = tv.tv_usec - start_tv.tv_usec;
if (tv.tv_usec < 0) if (tv.tv_usec < 0)
@ -175,25 +266,11 @@ int main(int argc, char **argv)
else else
fprintf(outfile, "%4ld.%06ld ", tv.tv_sec, tv.tv_usec); fprintf(outfile, "%4ld.%06ld ", tv.tv_sec, tv.tv_usec);
fprintf(outfile, "%-2d ", devno); /* channel number left aligned */ if ((mtu == CAN_MTU) && (fdfmt == 0))
can_asc(&cf, devno, nortrdlc, outfile);
else
canfd_asc(&cf, devno, mtu, outfile);
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.len); /* data frame */
for (i = 0; i < cf.len; i++) {
fprintf(outfile, " %02X", cf.data[i]);
}
}
}
if (crlf) if (crlf)
fprintf(outfile, "\r"); fprintf(outfile, "\r");
fprintf(outfile, "\n"); fprintf(outfile, "\n");

View File

@ -52,7 +52,7 @@
#define COMMENTSZ 200 #define COMMENTSZ 200
#define BUFSZ (sizeof("(1345212884.318850)") + IFNAMSIZ + 4 + CL_CFSZ + COMMENTSZ) /* for one line in the logfile */ #define BUFSZ (sizeof("(1345212884.318850)") + IFNAMSIZ + 4 + CL_CFSZ + COMMENTSZ) /* for one line in the logfile */
int main(int argc, char **argv) int main(void)
{ {
char buf[BUFSZ], timestamp[BUFSZ], device[BUFSZ], ascframe[BUFSZ]; char buf[BUFSZ], timestamp[BUFSZ], device[BUFSZ], ascframe[BUFSZ];
struct canfd_frame cf; struct canfd_frame cf;

View File

@ -57,22 +57,23 @@
void print_usage(char *prg) void print_usage(char *prg)
{ {
fprintf(stderr, "%s - userspace tool for serial line CAN interface driver SLCAN.\n", prg);
fprintf(stderr, "\nUsage: %s [options] tty\n\n", prg); fprintf(stderr, "\nUsage: %s [options] tty\n\n", prg);
fprintf(stderr, "Options: -o (send open command 'O\\r')\n"); fprintf(stderr, "Options:\n");
fprintf(stderr, " -l (send listen only command 'L\\r', overrides -o)\n"); fprintf(stderr, " -o (send open command 'O\\r')\n");
fprintf(stderr, " -c (send close command 'C\\r')\n"); fprintf(stderr, " -l (send listen only command 'L\\r', overrides -o)\n");
fprintf(stderr, " -f (read status flags with 'F\\r' to reset error states)\n"); fprintf(stderr, " -c (send close command 'C\\r')\n");
fprintf(stderr, " -s <speed> (set CAN speed 0..8)\n"); fprintf(stderr, " -f (read status flags with 'F\\r' to reset error states)\n");
fprintf(stderr, " -b <btr> (set bit time register value)\n"); fprintf(stderr, " -s <speed> (set CAN speed 0..8)\n");
fprintf(stderr, " -d (only detach line discipline)\n"); fprintf(stderr, " -b <btr> (set bit time register value)\n");
fprintf(stderr, " -w (attach - wait for keypess - detach)\n"); fprintf(stderr, " -d (only detach line discipline)\n");
fprintf(stderr, " -n <name> (assign created netdevice name)\n"); fprintf(stderr, " -w (attach - wait for keypess - detach)\n");
fprintf(stderr, " -n <name> (assign created netdevice name)\n");
fprintf(stderr, "\nExamples:\n"); fprintf(stderr, "\nExamples:\n");
fprintf(stderr, "slcan_attach -w -o -f -s6 -c /dev/ttyS1\n"); fprintf(stderr, "slcan_attach -w -o -f -s6 -c /dev/ttyS1\n\n");
fprintf(stderr, "slcan_attach /dev/ttyS1\n"); fprintf(stderr, "slcan_attach /dev/ttyS1\n\n");
fprintf(stderr, "slcan_attach -d /dev/ttyS1\n"); fprintf(stderr, "slcan_attach -d /dev/ttyS1\n\n");
fprintf(stderr, "slcan_attach -w -n can15 /dev/ttyS1\n"); fprintf(stderr, "slcan_attach -w -n can15 /dev/ttyS1\n\n");
fprintf(stderr, "\n");
exit(1); exit(1);
} }

View File

@ -72,22 +72,23 @@ static syslog_t syslogger = syslog;
void print_usage(char *prg) void print_usage(char *prg)
{ {
fprintf(stderr, "%s - userspace daemon for serial line CAN interface driver SLCAN.\n", prg);
fprintf(stderr, "\nUsage: %s [options] <tty> [canif-name]\n\n", prg); fprintf(stderr, "\nUsage: %s [options] <tty> [canif-name]\n\n", prg);
fprintf(stderr, "Options: -o (send open command 'O\\r')\n"); fprintf(stderr, "Options:\n");
fprintf(stderr, " -c (send close command 'C\\r')\n"); fprintf(stderr, " -o (send open command 'O\\r')\n");
fprintf(stderr, " -f (read status flags with 'F\\r' to reset error states)\n"); fprintf(stderr, " -c (send close command 'C\\r')\n");
fprintf(stderr, " -l (send listen only command 'L\\r', overrides -o)\n"); fprintf(stderr, " -f (read status flags with 'F\\r' to reset error states)\n");
fprintf(stderr, " -s <speed> (set CAN speed 0..8)\n"); fprintf(stderr, " -l (send listen only command 'L\\r', overrides -o)\n");
fprintf(stderr, " -S <speed> (set UART speed in baud)\n"); fprintf(stderr, " -s <speed> (set CAN speed 0..8)\n");
fprintf(stderr, " -t <type> (set UART flow control type 'hw' or 'sw')\n"); fprintf(stderr, " -S <speed> (set UART speed in baud)\n");
fprintf(stderr, " -b <btr> (set bit time register value)\n"); fprintf(stderr, " -t <type> (set UART flow control type 'hw' or 'sw')\n");
fprintf(stderr, " -F (stay in foreground; no daemonize)\n"); fprintf(stderr, " -b <btr> (set bit time register value)\n");
fprintf(stderr, " -h (show this help page)\n"); fprintf(stderr, " -F (stay in foreground; no daemonize)\n");
fprintf(stderr, " -h (show this help page)\n");
fprintf(stderr, "\nExamples:\n"); fprintf(stderr, "\nExamples:\n");
fprintf(stderr, "slcand -o -c -f -s6 ttyUSB0\n"); fprintf(stderr, "slcand -o -c -f -s6 ttyUSB0\n\n");
fprintf(stderr, "slcand -o -c -f -s6 ttyUSB0 can0\n"); fprintf(stderr, "slcand -o -c -f -s6 ttyUSB0 can0\n\n");
fprintf(stderr, "slcand -o -c -f -s6 /dev/ttyUSB0\n"); fprintf(stderr, "slcand -o -c -f -s6 /dev/ttyUSB0\n\n");
fprintf(stderr, "\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }

View File

@ -1,6 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* slcanpty.c - creates a pty for applications using the slcan ASCII protocol * slcanpty: adapter for applications using the slcan ASCII protocol
*
* slcanpty.c - creates a pty for applications using the slcan ASCII protocol
* and converts the ASCII data to a CAN network interface (and vice versa) * and converts the ASCII data to a CAN network interface (and vice versa)
* *
* Copyright (c)2009 Oliver Hartkopp * Copyright (c)2009 Oliver Hartkopp
@ -24,6 +26,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <libgen.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
@ -428,16 +431,18 @@ int main(int argc, char **argv)
/* check command line options */ /* check command line options */
if (argc != 3) { if (argc != 3) {
fprintf(stderr, "\n"); fprintf(stderr, "%s: adapter for applications using"
fprintf(stderr, "%s creates a pty for applications using" " the slcan ASCII protocol.\n", basename(argv[0]));
" the slcan ASCII protocol and\n", argv[0]); fprintf(stderr, "\n%s creates a pty for applications using"
" the slcan ASCII protocol and\n", basename(argv[0]));
fprintf(stderr, "converts the ASCII data to a CAN network" fprintf(stderr, "converts the ASCII data to a CAN network"
" interface (and vice versa)\n\n"); " interface (and vice versa)\n\n");
fprintf(stderr, "Usage: %s <pty> <can interface>\n", argv[0]); fprintf(stderr, "Usage: %s <pty> <can interface>\n", basename(argv[0]));
fprintf(stderr, "e.g. '%s /dev/ptyc0 can0' creates" fprintf(stderr, "\nExamples:\n");
" /dev/ttyc0 for the slcan application\n", argv[0]); fprintf(stderr, "%s /dev/ptyc0 can0 - creates /dev/ttyc0 for the slcan application\n\n",
basename(argv[0]));
fprintf(stderr, "e.g. for pseudo-terminal '%s %s can0' creates" fprintf(stderr, "e.g. for pseudo-terminal '%s %s can0' creates"
" /dev/pts/N\n", argv[0], DEVICE_NAME_PTMX); " /dev/pts/N\n", basename(argv[0]), DEVICE_NAME_PTMX);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
return 1; return 1;
} }

View File

@ -29,7 +29,7 @@
static const char help_msg[] = static const char help_msg[] =
"testj1939: demonstrate j1939 use\n" "testj1939: demonstrate j1939 use\n"
"Usage: testj1939 FROM TO\n" "Usage: testj1939 [OPTIONS] FROM TO\n"
" FROM / TO - or [IFACE][:[SA][,[PGN][,NAME]]]\n" " FROM / TO - or [IFACE][:[SA][,[PGN][,NAME]]]\n"
"Options:\n" "Options:\n"
" -v Print relevant API calls\n" " -v Print relevant API calls\n"
@ -46,7 +46,7 @@ static const char help_msg[] =
" -n Emit 64bit NAMEs in output\n" " -n Emit 64bit NAMEs in output\n"
" -w[TIME] Return after TIME (default 1) seconds\n" " -w[TIME] Return after TIME (default 1) seconds\n"
"\n" "\n"
"Example:\n" "Examples:\n"
"testj1939 can1 20\n" "testj1939 can1 20\n"
"\n" "\n"
; ;
@ -72,7 +72,8 @@ static void schedule_oneshot_itimer(double delay)
/* main */ /* main */
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int ret, sock, opt, j; int ret, sock, opt;
unsigned int j;
int verbose = 0; int verbose = 0;
socklen_t peernamelen; socklen_t peernamelen;
struct sockaddr_can sockname = { struct sockaddr_can sockname = {
@ -92,7 +93,8 @@ int main(int argc, char *argv[])
}; };
uint8_t dat[128]; uint8_t dat[128];
int valid_peername = 0; int valid_peername = 0;
int todo_send = 0, todo_recv = 0, todo_echo = 0, todo_prio = -1; unsigned int todo_send = 0;
int todo_recv = 0, todo_echo = 0, todo_prio = -1;
int todo_connect = 0, todo_names = 0, todo_wait = 0, todo_rebind = 0; int todo_connect = 0, todo_names = 0, todo_wait = 0, todo_rebind = 0;
int todo_broadcast = 0, todo_promisc = 0; int todo_broadcast = 0, todo_promisc = 0;
int no_bind = 0; int no_bind = 0;
@ -289,16 +291,16 @@ int main(int argc, char *argv[])
err(1, "sendto"); err(1, "sendto");
} }
if (todo_recv) { if (todo_recv) {
int i = 0; int i;
if (todo_names && peername.can_addr.j1939.name) if (todo_names && peername.can_addr.j1939.name)
printf("%016llx ", peername.can_addr.j1939.name); printf("%016llx ", peername.can_addr.j1939.name);
printf("%02x %05x:", peername.can_addr.j1939.addr, printf("%02x %05x:", peername.can_addr.j1939.addr,
peername.can_addr.j1939.pgn); peername.can_addr.j1939.pgn);
for (j = 0; j < ret; ++j, i++) { for (i = 0, j = 0; i < ret; ++i, j++) {
if (i == 8) { if (j == 8) {
printf("\n%05x ", j); printf("\n%05x ", j);
i = 0; j = 0;
} }
printf(" %02x", dat[j]); printf(" %02x", dat[j]);
} }