diff --git a/.gitignore b/.gitignore index ff624a8..fb2edb5 100644 --- a/.gitignore +++ b/.gitignore @@ -41,10 +41,10 @@ GNUmakefile.in /isotpserver /isotpsniffer /isotptun -/jacd -/jcat -/jspy -/jsr +/j1939acd +/j1939cat +/j1939spy +/j1939sr /log2asc /log2long /slcan_attach diff --git a/Android.mk b/Android.mk index bae170a..40564ec 100644 --- a/Android.mk +++ b/Android.mk @@ -1,6 +1,7 @@ LOCAL_PATH := $(call my-dir) PRIVATE_LOCAL_CFLAGS := -O2 -g -W -Wall \ + -Wno-error=unused-parameter \ -DSO_RXQ_OVFL=40 \ -DPF_CAN=29 \ -DAF_CAN=PF_CAN @@ -15,9 +16,104 @@ LOCAL_SRC_FILES := lib.c canframelen.c LOCAL_MODULE := libcan LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) +LOCAL_VENDOR_MODULE := true 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 # @@ -30,6 +126,7 @@ 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) @@ -45,6 +142,7 @@ 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) @@ -74,10 +172,10 @@ LOCAL_MODULE := bcmserver LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) +LOCAL_VENDOR_MODULE := true include $(BUILD_EXECUTABLE) - # # can-calc-bit-timing # @@ -89,6 +187,7 @@ LOCAL_MODULE := can-calc-bit-timing LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) +LOCAL_VENDOR_MODULE := true include $(BUILD_EXECUTABLE) @@ -104,6 +203,7 @@ 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) @@ -118,6 +218,7 @@ LOCAL_MODULE := canfdtest LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) +LOCAL_VENDOR_MODULE := true include $(BUILD_EXECUTABLE) @@ -133,6 +234,7 @@ 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) @@ -147,6 +249,7 @@ LOCAL_MODULE := cangw LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) +LOCAL_VENDOR_MODULE := true include $(BUILD_EXECUTABLE) @@ -162,6 +265,7 @@ 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) @@ -177,6 +281,7 @@ 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) @@ -191,6 +296,7 @@ LOCAL_MODULE := cansniffer LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) +LOCAL_VENDOR_MODULE := true include $(BUILD_EXECUTABLE) @@ -205,6 +311,7 @@ LOCAL_MODULE := isotpdump LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) +LOCAL_VENDOR_MODULE := true include $(BUILD_EXECUTABLE) @@ -219,6 +326,7 @@ LOCAL_MODULE := isotprecv LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) +LOCAL_VENDOR_MODULE := true include $(BUILD_EXECUTABLE) @@ -233,6 +341,7 @@ LOCAL_MODULE := isotpsend LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) +LOCAL_VENDOR_MODULE := true include $(BUILD_EXECUTABLE) @@ -247,6 +356,7 @@ LOCAL_MODULE := isotpserver LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) +LOCAL_VENDOR_MODULE := true include $(BUILD_EXECUTABLE) @@ -257,10 +367,11 @@ include $(BUILD_EXECUTABLE) include $(CLEAR_VARS) LOCAL_SRC_FILES := isotpsniffer.c -LOCAL_MODULE := isotpsniffer.c +LOCAL_MODULE := isotpsniffer LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) +LOCAL_VENDOR_MODULE := true include $(BUILD_EXECUTABLE) @@ -275,6 +386,7 @@ LOCAL_MODULE := isotptun LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) +LOCAL_VENDOR_MODULE := true include $(BUILD_EXECUTABLE) @@ -289,6 +401,7 @@ LOCAL_MODULE := isotpperf LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) +LOCAL_VENDOR_MODULE := true include $(BUILD_EXECUTABLE) @@ -304,6 +417,23 @@ 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) + +# +# 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) @@ -319,6 +449,7 @@ 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) @@ -333,6 +464,7 @@ LOCAL_MODULE := slcan_attach LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) +LOCAL_VENDOR_MODULE := true include $(BUILD_EXECUTABLE) @@ -347,6 +479,7 @@ LOCAL_MODULE := slcand LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) +LOCAL_VENDOR_MODULE := true include $(BUILD_EXECUTABLE) @@ -361,5 +494,6 @@ LOCAL_MODULE := slcanpty LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS) +LOCAL_VENDOR_MODULE := true include $(BUILD_EXECUTABLE) diff --git a/CMakeLists.txt b/CMakeLists.txt index e0a2fe8..d0f83ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,10 +37,10 @@ set(PROGRAMS_CANLIB ) set(PROGRAMS_J1939 - jacd - jcat - jspy - jsr + j1939acd + j1939cat + j1939spy + j1939sr testj1939 ) diff --git a/GNUmakefile.am b/GNUmakefile.am index a34a40d..37b68a5 100644 --- a/GNUmakefile.am +++ b/GNUmakefile.am @@ -59,10 +59,10 @@ bin_PROGRAMS = \ isotpserver \ isotpsniffer \ isotptun \ - jacd \ - jcat \ - jspy \ - jsr \ + j1939acd \ + j1939cat \ + j1939spy \ + j1939sr \ log2asc \ log2long \ slcan_attach \ @@ -70,10 +70,10 @@ bin_PROGRAMS = \ slcanpty \ testj1939 -jacd_LDADD = libj1939.la -jcat_LDADD = libj1939.la -jspy_LDADD = libj1939.la -jsr_LDADD = libj1939.la +j1939acd_LDADD = libj1939.la +j1939cat_LDADD = libj1939.la +j1939spy_LDADD = libj1939.la +j1939sr_LDADD = libj1939.la testj1939_LDADD = libj1939.la EXTRA_DIST = \ diff --git a/Makefile b/Makefile index 6d87a46..b7dad97 100644 --- a/Makefile +++ b/Makefile @@ -67,10 +67,10 @@ PROGRAMS_ISOTP := \ isotptun PROGRAMS_J1939 := \ - jacd \ - jcat \ - jspy \ - jsr \ + j1939acd \ + j1939cat \ + j1939spy \ + j1939sr \ testj1939 PROGRAMS_SLCAN := \ @@ -120,10 +120,10 @@ canplayer.o: lib.h cansend.o: lib.h log2asc.o: lib.h log2long.o: lib.h -jacd.o: libj1939.h -jcat.o: libj1939.h -jspy.o: libj1939.h -jsr.o: libj1939.h +j1939acd.o: libj1939.h +j1939cat.o: libj1939.h +j1939spy.o: libj1939.h +j1939sr.o: libj1939.h testj1939.o: libj1939.h canframelen.o: canframelen.h @@ -136,9 +136,9 @@ canplayer: canplayer.o lib.o cansend: cansend.o lib.o log2asc: log2asc.o lib.o log2long: log2long.o lib.o -jacd: jacd.o libj1939.o -jcat: jcat.o libj1939.o -jspy: jspy.o libj1939.o -jsr: jsr.o libj1939.o +j1939acd: j1939acd.o libj1939.o +j1939cat: j1939cat.o libj1939.o +j1939spy: j1939spy.o libj1939.o +j1939sr: j1939sr.o libj1939.o testj1939: testj1939.o libj1939.o canbusload: canbusload.o canframelen.o diff --git a/README.md b/README.md index 5a17610..1011cf4 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ subsystem (aka SocketCAN): * cansend : send a single frame * cangen : generate (random) CAN traffic * 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 * canlogserver : log CAN frames from a remote/local host diff --git a/asc2log.c b/asc2log.c index 59f2f98..de619c0 100644 --- a/asc2log.c +++ b/asc2log.c @@ -57,16 +57,20 @@ #include "lib.h" +#define BUFLEN 400 /* CAN FD mode lines can be pretty long */ + extern int optind, opterr, optopt; 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, "Options: -I (default stdin)\n"); - fprintf(stderr, " -O (default stdout)\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, "\t-I \t(default stdin)\n"); + fprintf(stderr, "\t-O \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); @@ -75,11 +79,10 @@ void prframe(FILE *file, struct timeval *tv, int dev, struct can_frame *cf) { else fprintf(file, "canX "); - /* no CAN FD support so far */ - fprint_canframe(file, (struct canfd_frame *)cf, "\n", 0, CAN_MAX_DLEN); + fprint_canframe(file, cf, "\n", 0, 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') { 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 + 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) { - char ctmp[10]; - int itmp; - 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 */ if (!setlocale(LC_TIME, "en_US")) { @@ -137,29 +333,41 @@ int get_date(struct timeval *tv, char *date) { return 1; } - if (!strptime(date, "%B %d %r %Y", &tms)) - return 1; + if (!strptime(date, "%B %d %I:%M:%S %p %Y", &tms)) { + /* 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 { /* 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")) { fprintf(stderr, "Setting locale to 'de_DE' failed!\n"); return 1; } - if (!strptime(date, "%B %d %T %Y", &tms)) - return 1; + if (!strptime(date, "%B %d %H:%M:%S %Y", &tms)) { + /* 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", - //tms.tm_hour, tms.tm_min, tms.tm_sec, + //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, msecs, //tms.tm_mday, tms.tm_mon+1, tms.tm_year+1900); tv->tv_sec = mktime(&tms); + tv->tv_usec = msecs * 1000; if (tv->tv_sec < 0) return 1; @@ -169,24 +377,17 @@ int get_date(struct timeval *tv, char *date) { int main(int argc, char **argv) { - char buf[100], tmp1[100], tmp2[100]; + char buf[BUFLEN], tmp1[BUFLEN], tmp2[BUFLEN]; FILE *infile = stdin; FILE *outfile = stdout; static int verbose; - struct can_frame cf; - static struct timeval tv; /* current frame timestamp */ - static struct timeval read_tv; /* frame timestamp from ASC file */ + static struct timeval tmp_tv; /* tmp frame timestamp from ASC file */ static struct timeval date_tv; /* date of the ASC file */ static int dplace; /* decimal place 4, 5 or 6 or uninitialized */ static char base; /* 'd'ec or 'h'ex */ static char timestamps; /* 'a'bsolute or 'r'elative */ - - int interface; - char rtr; - int dlc = 0; - int data[8]; - int i, found, opt; + int opt; while ((opt = getopt(argc, argv, "I:O:v?")) != -1) { 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 */ @@ -264,7 +465,7 @@ int main(int argc, char **argv) } /* 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); if (verbose) 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 */ /* so try to get CAN frames and ErrorFrames and convert them */ - /* 0.002367 1 390x Rx d 8 17 00 14 00 C0 00 08 00 */ - - found = 0; /* found valid CAN frame ? */ - - if (base == 'h') { /* check for CAN frames with hexadecimal values */ - - if (sscanf(buf, "%ld.%ld %d %s %*s %c %d %x %x %x %x %x %x %x %x", - &read_tv.tv_sec, &read_tv.tv_usec, &interface, - tmp1, &rtr, &dlc, - &data[0], &data[1], &data[2], &data[3], - &data[4], &data[5], &data[6], &data[7] - ) == dlc + 6 ) { - - found = 1; - get_can_id(&cf, tmp1, 16); - } - - } else { /* check for CAN frames with decimal values */ - - if (sscanf(buf, "%ld.%ld %d %s %*s %c %d %d %d %d %d %d %d %d %d", - &read_tv.tv_sec, &read_tv.tv_usec, &interface, - tmp1, &rtr, &dlc, - &data[0], &data[1], &data[2], &data[3], - &data[4], &data[5], &data[6], &data[7] - ) == dlc + 6 ) { - - found = 1; - get_can_id(&cf, tmp1, 10); - } - } - - if (found) { - if (rtr == 'r') - cf.can_id |= CAN_RTR_FLAG; - - cf.can_dlc = dlc & 0x0FU; - for (i=0; i #include #include +#include #include #include @@ -131,17 +132,16 @@ static inline void *netdev_priv(const struct net_device *dev) static void print_usage(char *cmd) { + printf("%s - calculate CAN bit timing parameters.\n", cmd); printf("Usage: %s [options] []\n" - "\tOptions:\n" - "\t-q : don't print header line\n" - "\t-l : list all support CAN controller names\n" - "\t-b : bit-rate in bits/sec\n" - "\t-s : sample-point in one-tenth of a percent\n" + "Options:\n" + "\t-q don't print header line\n" + "\t-l list all support CAN controller names\n" + "\t-b bit-rate in bits/sec\n" + "\t-s sample-point in one-tenth of a percent\n" "\t or 0 for CIA recommended sample points\n" - "\t-c : real CAN system clock in Hz\n", + "\t-c real CAN system clock in Hz\n", cmd); - - exit(EXIT_FAILURE); } 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; - while ((opt = getopt(argc, argv, "b:c:lqs:")) != -1) { + while ((opt = getopt(argc, argv, "b:c:lqs:?")) != -1) { switch (opt) { case 'b': bitrate_nominal = atoi(optarg); @@ -660,14 +660,22 @@ int main(int argc, char *argv[]) spt_nominal = strtoul(optarg, NULL, 10); break; + case '?': + print_usage(basename(argv[0])); + exit(EXIT_SUCCESS); + break; + default: - print_usage(argv[0]); + print_usage(basename(argv[0])); + exit(EXIT_FAILURE); break; } } - if (argc > optind + 1) + if (argc > optind + 1) { print_usage(argv[0]); + exit(EXIT_FAILURE); + } if (argc == optind + 1) name = argv[optind]; @@ -677,8 +685,10 @@ int main(int argc, char *argv[]) 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]); + exit(EXIT_FAILURE); + } for (i = 0; i < ARRAY_SIZE(can_calc_consts); i++) { if (name && strcmp(can_calc_consts[i].bittiming_const.name, name)) diff --git a/can-j1939-kickstart.md b/can-j1939-kickstart.md index bc8f9de..721656a 100644 --- a/can-j1939-kickstart.md +++ b/can-j1939-kickstart.md @@ -44,7 +44,7 @@ You should have this output in terminal 1 40 02300: 01 23 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: diff --git a/canbusload.c b/canbusload.c index f5f130b..ff07b60 100644 --- a/canbusload.c +++ b/canbusload.c @@ -1,6 +1,6 @@ /* 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 * All rights reserved. @@ -91,14 +91,16 @@ static char *prg; void print_usage(char *prg) { + fprintf(stderr, "%s - monitor CAN bus load.\n", prg); fprintf(stderr, "\nUsage: %s [options] +\n", prg); fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg); - fprintf(stderr, "Options: -t (show current time on the first line)\n"); - fprintf(stderr, " -c (colorize lines)\n"); - fprintf(stderr, " -b (show bargraph in %d%% resolution)\n", PERCENTRES); - fprintf(stderr, " -r (redraw the terminal - similar to top)\n"); - fprintf(stderr, " -i (ignore bitstuffing in bandwidth calculation)\n"); - fprintf(stderr, " -e (exact calculation of stuffed bits)\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -t (show current time on the first line)\n"); + fprintf(stderr, " -c (colorize lines)\n"); + fprintf(stderr, " -b (show bargraph in %d%% resolution)\n", PERCENTRES); + fprintf(stderr, " -r (redraw the terminal - similar to top)\n"); + fprintf(stderr, " -i (ignore bitstuffing in bandwidth calculation)\n"); + fprintf(stderr, " -e (exact calculation of stuffed bits)\n"); fprintf(stderr, "\n"); fprintf(stderr, "Up to %d CAN interfaces with mandatory bitrate can be specified on the \n", MAXSOCK); fprintf(stderr, "commandline in the form: @\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, "For each given interface the data is presented in one line which contains:\n\n"); fprintf(stderr, "(interface) (received CAN frames) (used bits total) (used bits for payload)\n"); - fprintf(stderr, "\nExample:\n"); + fprintf(stderr, "\nExamples:\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, " can0@100000 805 74491 36656 74%% |XXXXXXXXXXXXXX......|\n"); @@ -298,7 +300,7 @@ int main(int argc, char **argv) ptr = argv[optind+i]; 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); return 1; } @@ -322,7 +324,7 @@ int main(int argc, char **argv) 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); return 1; } @@ -394,7 +396,7 @@ int main(int argc, char **argv) return 1; } - if (nbytes < sizeof(struct can_frame)) { + if (nbytes < (int)sizeof(struct can_frame)) { fprintf(stderr, "read: incomplete CAN frame\n"); return 1; } diff --git a/candump.c b/candump.c index 16382d1..846c706 100644 --- a/candump.c +++ b/candump.c @@ -116,9 +116,11 @@ static volatile int running = 1; void print_usage(char *prg) { + fprintf(stderr, "%s - dump CAN bus traffic.\n", prg); fprintf(stderr, "\nUsage: %s [options] +\n", prg); fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg); - fprintf(stderr, "Options: -t (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -t (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, " -c (increment color mode level)\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, "Up to %d CAN interfaces with optional filter sets can be specified\n", MAXSOCK); fprintf(stderr, "on the commandline in the form: [,filter]*\n"); - fprintf(stderr, "\nComma separated filters can be specified for each given CAN interface:\n"); - fprintf(stderr, " : (matches when & mask == can_id & mask)\n"); - fprintf(stderr, " ~ (matches when & mask != can_id & mask)\n"); - fprintf(stderr, " # (set error frame filter, see include/linux/can/error.h)\n"); - fprintf(stderr, " [j|J] (join the given CAN filters - logical AND semantic)\n"); + fprintf(stderr, "\nFilters:\n"); + fprintf(stderr, " Comma separated filters can be specified for each given CAN interface:\n"); + fprintf(stderr, " :\n (matches when & mask == can_id & mask)\n"); + fprintf(stderr, " ~\n (matches when & mask != can_id & mask)\n"); + fprintf(stderr, " #\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, "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, "\nUse interface name '%s' to receive from all CAN interfaces.\n", ANYDEV); fprintf(stderr, "\nExamples:\n"); - fprintf(stderr, "%s -c -c -ta can0,123:7FF,400:700,#000000FF can2,400~7F0 can3 can8\n", prg); - fprintf(stderr, "%s -l any,0~0,#FFFFFFFF (log only error frames but no(!) data frames)\n", prg); - fprintf(stderr, "%s -l any,0:0,#FFFFFFFF (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,123:7FF (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 -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\n (log only error frames but no(!) 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\n (match only for extended CAN ID 12345678)\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\n (matches CAN ID 123 - only SFF and non-RTR frames)\n", prg); fprintf(stderr, "\n"); } @@ -198,7 +201,7 @@ int idx2dindex(int ifidx, int socket) { if (ioctl(socket, SIOCGIFNAME, &ifr) < 0) 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); strcpy(devname[i], ifr.ifr_name); diff --git a/canfdtest.c b/canfdtest.c index cf59a3a..ba4bfe6 100644 --- a/canfdtest.c +++ b/canfdtest.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -48,31 +49,37 @@ static int verbose; static int sockfd; static int test_loops; static int exit_sig; +static int inflight_count = CAN_MSG_COUNT; static void print_usage(char *prg) { fprintf(stderr, + "%s - Full-duplex test program (DUT and host part).\n" "Usage: %s [options] \n" "\n" - "Options: -v (low verbosity)\n" + "Options:\n" + " -v (low verbosity)\n" " -vv (high verbosity)\n" " -g (generate messages)\n" " -l COUNT (test loop count)\n" + " -f COUNT (number of frames in flight, default: %d)\n" "\n" "With the option '-g' CAN messages are generated and checked\n" "on , otherwise all messages received on the\n" " are sent back incrementing the CAN id and\n" "all data bytes. The program can be aborted with ^C.\n" "\n" - "Example:\n" - "\ton DUT : %s -v can0\n" - "\ton Host: %s -g -v can2\n", - prg, prg, prg); + "Examples:\n" + "\ton DUT:\n" + "%s -v can0\n" + "\ton Host:\n" + "%s -g -v can2\n", + prg, prg, CAN_MSG_COUNT, prg, prg); 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; @@ -82,12 +89,12 @@ static void print_frame(struct can_frame *frame, int inc) } else { printf("[%d]", frame->can_dlc); for (i = 0; i < frame->can_dlc; i++) - printf(" %02x", frame->data[i] + inc); + printf(" %02x", (uint8_t)(frame->data[i] + inc)); } 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: "); print_frame(exp, inc); @@ -109,8 +116,8 @@ static void compare_frame(struct can_frame *exp, struct can_frame *rec, int inc) running = 0; } else { for (i = 0; i < rec->can_dlc; i++) { - if (rec->data[i] != ((exp->data[i] + inc) & 0xff)) { - printf("Databyte %x mismatch !\n", i); + if (rec->data[i] != (uint8_t)(exp->data[i] + inc)) { + printf("Databyte %x mismatch!\n", i); print_compare(exp, rec, inc); running = 0; @@ -192,11 +199,47 @@ static int send_frame(struct can_frame *frame) 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) { unsigned int frame_count = 0; struct can_frame frame; - int i; while (running) { if (recv_frame(&frame)) @@ -205,19 +248,11 @@ static int can_echo_dut(void) if (verbose == 1) { echo_progress(frame.data[0]); } else if (verbose > 1) { - printf("%04x: ", frame.can_id); - 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"); + print_frame(&frame, 0); } - frame.can_id++; - for (i = 0; i < frame.can_dlc; i++) - frame.data[i]++; + + check_frame(&frame); + inc_frame(&frame); if (send_frame(&frame)) return -1; @@ -236,15 +271,26 @@ static int can_echo_dut(void) static int can_echo_gen(void) { - struct can_frame tx_frames[CAN_MSG_COUNT]; - int recv_tx[CAN_MSG_COUNT]; + struct can_frame *tx_frames; + int *recv_tx; struct can_frame rx_frame; unsigned char counter = 0; int send_pos = 0, recv_rx_pos = 0, recv_tx_pos = 0, unprocessed = 0, loops = 0; + int err = 0; 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) { - if (unprocessed < CAN_MSG_COUNT) { + if (unprocessed < inflight_count) { /* still send messages */ tx_frames[send_pos].can_dlc = CAN_MSG_LEN; 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++) tx_frames[send_pos].data[i] = counter + i; - if (send_frame(&tx_frames[send_pos])) - return -1; + if (send_frame(&tx_frames[send_pos])) { + err = -1; + goto out_free; + } send_pos++; - if (send_pos == CAN_MSG_COUNT) + if (send_pos == inflight_count) send_pos = 0; unprocessed++; if (verbose == 1) @@ -268,8 +316,10 @@ static int can_echo_gen(void) else millisleep(1); } else { - if (recv_frame(&rx_frame)) - return -1; + if (recv_frame(&rx_frame)) { + err = -1; + goto out_free; + } if (verbose > 1) 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); recv_tx[recv_tx_pos] = 1; recv_tx_pos++; - if (recv_tx_pos == CAN_MSG_COUNT) + if (recv_tx_pos == inflight_count) recv_tx_pos = 0; continue; } else { @@ -290,7 +340,7 @@ static int can_echo_gen(void) /* compare with expected */ compare_frame(&tx_frames[recv_rx_pos], &rx_frame, 1); recv_rx_pos++; - if (recv_rx_pos == CAN_MSG_COUNT) + if (recv_rx_pos == inflight_count) recv_rx_pos = 0; } @@ -304,7 +354,12 @@ static int can_echo_gen(void) 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[]) @@ -320,20 +375,24 @@ int main(int argc, char *argv[]) signal(SIGHUP, 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) { case 'v': verbose++; break; + case 'f': + inflight_count = atoi(optarg); + break; case 'l': - test_loops = atoi(optarg);; + test_loops = atoi(optarg); break; case 'g': echo_gen = 1; break; + case '?': default: print_usage(basename(argv[0])); break; diff --git a/cangen.c b/cangen.c index 9a1914b..e26c08b 100644 --- a/cangen.c +++ b/cangen.c @@ -1,6 +1,6 @@ /* 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 * All rights reserved. @@ -66,6 +66,7 @@ #include "lib.h" #define DEFAULT_GAP 200 /* ms */ +#define DEFAULT_BURST_COUNT 1 #define MODE_RANDOM 0 #define MODE_INCREMENT 1 @@ -78,17 +79,20 @@ static unsigned long long enobufs_count; 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] \n", prg); - fprintf(stderr, "Options: -g (gap in milli seconds " + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -g (gap in milli seconds " "- default: %d ms)\n", DEFAULT_GAP); fprintf(stderr, " -e (generate extended frame mode " "(EFF) CAN frames)\n"); fprintf(stderr, " -f (generate CAN FD CAN frames)\n"); fprintf(stderr, " -b (generate CAN FD CAN frames" " 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, " -m (mix -e -f -b -R frames)\n"); + fprintf(stderr, " -m (mix -e -f -b -E -R frames)\n"); fprintf(stderr, " -I (CAN ID" " generation mode - see below)\n"); fprintf(stderr, " -L (CAN data length code (dlc)" @@ -103,28 +107,30 @@ void print_usage(char *prg) " write() syscalls)\n"); fprintf(stderr, " -x (disable local loopback of " "generated CAN frames)\n"); + fprintf(stderr, " -c (number of messages to send in burst, " + "default 1)\n"); fprintf(stderr, " -v (increment verbose level for " "printing sent CAN frames)\n\n"); fprintf(stderr, "Generation modes:\n"); - fprintf(stderr, "'r' => random values (default)\n"); - fprintf(stderr, "'i' => increment values\n"); - fprintf(stderr, " => fix value using \n\n"); + fprintf(stderr, " 'r' => random values (default)\n"); + fprintf(stderr, " 'i' => increment values\n"); + fprintf(stderr, " => fix value using \n\n"); fprintf(stderr, "When incrementing the CAN data the data length code " "minimum is set to 1.\n"); fprintf(stderr, "CAN IDs and data content are given and expected in hexadecimal values.\n\n"); fprintf(stderr, "Examples:\n"); - fprintf(stderr, "%s vcan0 -g 4 -I 42A -L 1 -D i -v -v ", prg); - fprintf(stderr, "(fixed CAN ID and length, inc. data)\n"); - fprintf(stderr, "%s vcan0 -e -L i -v -v -v ", prg); - fprintf(stderr, "(generate EFF frames, incr. length)\n"); - fprintf(stderr, "%s vcan0 -D 11223344DEADBEEF -L 8 ", prg); - fprintf(stderr, "(fixed CAN data payload and length)\n"); - fprintf(stderr, "%s vcan0 -g 0 -i -x ", prg); - fprintf(stderr, "(full load test ignoring -ENOBUFS)\n"); - fprintf(stderr, "%s vcan0 -g 0 -p 10 -x ", prg); - fprintf(stderr, "(full load test with polling, 10ms timeout)\n"); - fprintf(stderr, "%s vcan0 ", prg); - fprintf(stderr, "(my favourite default :)\n\n"); + fprintf(stderr, "%s vcan0 -g 4 -I 42A -L 1 -D i -v -v\n", prg); + fprintf(stderr, "\t(fixed CAN ID and length, inc. data)\n"); + fprintf(stderr, "%s vcan0 -e -L i -v -v -v\n", prg); + fprintf(stderr, "\t(generate EFF frames, incr. length)\n"); + fprintf(stderr, "%s vcan0 -D 11223344DEADBEEF -L 8\n", prg); + fprintf(stderr, "\t(fixed CAN data payload and length)\n"); + fprintf(stderr, "%s vcan0 -g 0 -i -x\n", prg); + fprintf(stderr, "\t(full load test ignoring -ENOBUFS)\n"); + fprintf(stderr, "%s vcan0 -g 0 -p 10 -x\n", prg); + fprintf(stderr, "\t(full load test with polling, 10ms timeout)\n"); + fprintf(stderr, "%s vcan0\n", prg); + fprintf(stderr, "\t(my favourite default :)\n\n"); } void sigterm(int signo) @@ -135,11 +141,13 @@ void sigterm(int signo) int main(int argc, char **argv) { double gap = DEFAULT_GAP; + unsigned long burst_count = DEFAULT_BURST_COUNT; unsigned long polltimeout = 0; unsigned char ignore_enobufs = 0; unsigned char extended = 0; unsigned char canfd = 0; unsigned char brs = 0; + unsigned char esi = 0; unsigned char mix = 0; unsigned char id_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 rtr_frame = 0; int count = 0; + unsigned long burst_sent_count = 0; int mtu, maxdlen; uint64_t incdata = 0; int incdlc = 0; @@ -175,7 +184,7 @@ int main(int argc, char **argv) signal(SIGHUP, 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) { case 'i': @@ -199,6 +208,11 @@ int main(int argc, char **argv) canfd = 1; break; + case 'E': + esi = 1; /* error state indicator implies CAN FD */ + canfd = 1; + break; + case 'm': mix = 1; canfd = 1; /* to switch the socket into CAN FD mode */ @@ -240,6 +254,10 @@ int main(int argc, char **argv) } break; + case 'c': + burst_count = strtoul(optarg, NULL, 10); + break; + case 'v': verbose++; break; @@ -369,6 +387,8 @@ int main(int argc, char **argv) maxdlen = CANFD_MAX_DLEN; if (brs) frame.flags |= CANFD_BRS; + if (esi) + frame.flags |= CANFD_ESI; } else { mtu = CAN_MTU; maxdlen = CAN_MAX_DLEN; @@ -458,10 +478,14 @@ resend: 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)) return 1; + if (burst_sent_count >= burst_count) + burst_sent_count = 0; + if (id_mode == MODE_INCREMENT) frame.can_id++; @@ -490,8 +514,10 @@ resend: i = random(); extended = i&1; canfd = i&2; - if (canfd) + if (canfd) { brs = i&4; + esi = i&8; + } rtr_frame = ((i&24) == 24); /* reduce RTR frames to 1/4 */ } } diff --git a/cangw.c b/cangw.c index 52314f6..715a44f 100644 --- a/cangw.c +++ b/cangw.c @@ -80,7 +80,7 @@ struct fdmodattr { /* some netlink helpers stolen from iproute2 package */ #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 alen) @@ -88,7 +88,7 @@ int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, int len = RTA_LENGTH(alen); 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", maxlen); return -1; @@ -222,55 +222,60 @@ void print_cs_crc8(struct cgw_csum_crc8 *cs_crc8) 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, "Commands: -A (add a new rule)\n"); - fprintf(stderr, " -D (delete a rule)\n"); - fprintf(stderr, " -F (flush / delete all rules)\n"); - fprintf(stderr, " -L (list all rules)\n"); - fprintf(stderr, "Mandatory: -s (source netdevice)\n"); - fprintf(stderr, " -d (destination netdevice)\n"); - fprintf(stderr, "Options: -X (this is a CAN FD rule)\n"); - fprintf(stderr, " -t (preserve src_dev rx timestamp)\n"); - fprintf(stderr, " -e (echo sent frames - recommended on vcanx)\n"); - fprintf(stderr, " -i (allow to route to incoming interface)\n"); - fprintf(stderr, " -u (user defined modification identifier)\n"); - fprintf(stderr, " -l (limit the number of frame hops / routings)\n"); - fprintf(stderr, " -f (set CAN filter)\n"); - fprintf(stderr, " -m (set Classic CAN frame modifications)\n"); - fprintf(stderr, " -M (set CAN FD frame modifications)\n"); - fprintf(stderr, " -x ::: (XOR checksum)\n"); - fprintf(stderr, " -c ::::: (CRC8 cs)\n"); - fprintf(stderr, " -p :[] (CRC8 checksum profile & parameters)\n"); + fprintf(stderr, "Commands:\n"); + fprintf(stderr, " -A (add a new rule)\n"); + fprintf(stderr, " -D (delete a rule)\n"); + fprintf(stderr, " -F (flush / delete all rules)\n"); + fprintf(stderr, " -L (list all rules)\n"); + fprintf(stderr, "Mandatory:\n"); + fprintf(stderr, " -s (source netdevice)\n"); + fprintf(stderr, " -d (destination netdevice)\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -X (this is a CAN FD rule)\n"); + fprintf(stderr, " -t (preserve src_dev rx timestamp)\n"); + fprintf(stderr, " -e (echo sent frames - recommended on vcanx)\n"); + fprintf(stderr, " -i (allow to route to incoming interface)\n"); + fprintf(stderr, " -u (user defined modification identifier)\n"); + fprintf(stderr, " -l (limit the number of frame hops / routings)\n"); + fprintf(stderr, " -f (set CAN filter)\n"); + fprintf(stderr, " -m (set Classic CAN frame modifications)\n"); + fprintf(stderr, " -M (set CAN FD frame modifications)\n"); + fprintf(stderr, " -x ::: (XOR checksum)\n"); + fprintf(stderr, " -c ::::: (CRC8 cs)\n"); + fprintf(stderr, " -p :[] (CRC8 checksum profile & parameters)\n"); fprintf(stderr, "\nValues are given and expected in hexadecimal values. Leading 0s can be omitted.\n"); fprintf(stderr, "\n"); - fprintf(stderr, " is a CAN identifier filter\n"); - fprintf(stderr, " : (matches when & mask == can_id & mask)\n"); - fprintf(stderr, " ~ (matches when & mask != can_id & mask)\n"); + fprintf(stderr, " is a CAN identifier filter:\n"); + fprintf(stderr, " : (matches when & mask == can_id & mask)\n"); + fprintf(stderr, " ~ (matches when & mask != can_id & mask)\n"); fprintf(stderr, "\n"); fprintf(stderr, " is a CAN frame modification instruction consisting of\n"); fprintf(stderr, "::..\n"); - fprintf(stderr, " - is one of 'AND' 'OR' 'XOR' 'SET'\n"); - fprintf(stderr, " - is _one_ or _more_ of 'I'dentifier 'L'ength 'D'ata\n"); - fprintf(stderr, " - is an u32 value containing the CAN Identifier\n"); - fprintf(stderr, " - is an u8 value containing the data length code (0 .. 8)\n"); - fprintf(stderr, " - is always eight(!) u8 values containing the CAN frames data\n"); + fprintf(stderr, " is one of 'AND' 'OR' 'XOR' 'SET'\n"); + fprintf(stderr, " is _one_ or _more_ of 'I'dentifier 'L'ength 'D'ata\n"); + fprintf(stderr, " is an u32 value containing the CAN Identifier\n"); + fprintf(stderr, " is an u8 value containing the data length code (0 .. 8)\n"); + fprintf(stderr, " is always eight(!) u8 values containing the CAN frames data\n"); + fprintf(stderr, "\n"); fprintf(stderr, " is a CAN FD frame modification instruction consisting of\n"); fprintf(stderr, "::...\n"); - fprintf(stderr, " - is one of 'AND' 'OR' 'XOR' 'SET'\n"); - fprintf(stderr, " - is _one_ or _more_ of 'I'd 'F'lags 'L'ength 'D'ata\n"); - fprintf(stderr, " - is an u32 value containing the CAN FD Identifier\n"); - fprintf(stderr, " - is an u8 value containing CAN FD flags (CANFD_BRS, CANFD_ESI)\n"); - fprintf(stderr, " - is an u8 value containing the data length (0 .. 64)\n"); - fprintf(stderr, " - is always 64(!) u8 values containing the CAN FD frames data\n"); + fprintf(stderr, " is one of 'AND' 'OR' 'XOR' 'SET'\n"); + fprintf(stderr, " is _one_ or _more_ of 'I'd 'F'lags 'L'ength 'D'ata\n"); + fprintf(stderr, " is an u32 value containing the CAN FD Identifier\n"); + fprintf(stderr, " is an u8 value containing CAN FD flags (CANFD_BRS, CANFD_ESI)\n"); + fprintf(stderr, " is an u8 value containing the data length (0 .. 64)\n"); + fprintf(stderr, " 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, "\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, "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' (SFFID_XOR) - add u8 value (can_id & 0xFF) ^ (can_id >> 8 & 0xFF)\n", CGW_CRC8PRF_SFFID_XOR); + 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' (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"); } diff --git a/canlogserver.c b/canlogserver.c index 4429ccd..0f7f255 100644 --- a/canlogserver.c +++ b/canlogserver.c @@ -89,7 +89,8 @@ void print_usage(char *prg) { fprintf(stderr, "\nUsage: %s [options] +\n", prg); fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg); - fprintf(stderr, "Options: -m (ID filter mask. Default 0x00000000) *\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -m (ID filter mask. Default 0x00000000) *\n"); fprintf(stderr, " -v (ID filter value. Default 0x00000000) *\n"); fprintf(stderr, " -i <0|1> (invert the specified ID filter) *\n"); fprintf(stderr, " -e (mask for error frames)\n"); @@ -139,7 +140,7 @@ int idx2dindex(int ifidx, int socket) if (ioctl(socket, SIOCGIFNAME, &ifr) < 0) 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); strcpy(devname[i], ifr.ifr_name); diff --git a/canplayer.c b/canplayer.c index 7932f7a..1482dc8 100644 --- a/canplayer.c +++ b/canplayer.c @@ -77,30 +77,32 @@ extern int optind, opterr, optopt; void print_usage(char *prg) { + fprintf(stderr, "%s - replay a compact CAN frame logfile to CAN devices.\n", prg); fprintf(stderr, "\nUsage: %s [interface assignment]*\n\n", prg); - fprintf(stderr, "Options: -I (default stdin)\n"); - fprintf(stderr, " -l " - "(process input file times)\n" - " " - "(Use 'i' for infinite loop - default: %d)\n", DEFAULT_LOOPS); - fprintf(stderr, " -t (ignore timestamps: " - "send frames immediately)\n"); - fprintf(stderr, " -g (gap in milli " - "seconds - default: %d ms)\n", DEFAULT_GAP); - fprintf(stderr, " -s (skip gaps in " - "timestamps > 's' seconds)\n"); - fprintf(stderr, " -x (disable local " - "loopback of sent CAN frames)\n"); - fprintf(stderr, " -v (verbose: print " - "sent CAN frames)\n\n"); - fprintf(stderr, "Interface assignment: 0..n assignments like " - "=\n"); - fprintf(stderr, "e.g. vcan2=can0 ( send frames received from can0 on " - "vcan2 )\n"); - fprintf(stderr, "extra hook: stdout=can0 ( print logfile line marked with can0 on " - "stdout )\n"); - fprintf(stderr, "No assignments => send frames to the interface(s) they " - "had been received from.\n\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -I (default stdin)\n"); + fprintf(stderr, " -l " + "(process input file times)\n" + " " + "(Use 'i' for infinite loop - default: %d)\n", DEFAULT_LOOPS); + fprintf(stderr, " -t (ignore timestamps: " + "send frames immediately)\n"); + fprintf(stderr, " -g (gap in milli " + "seconds - default: %d ms)\n", DEFAULT_GAP); + fprintf(stderr, " -s (skip gaps in " + "timestamps > 's' seconds)\n"); + fprintf(stderr, " -x (disable local " + "loopback of sent CAN frames)\n"); + fprintf(stderr, " -v (verbose: print " + "sent CAN frames)\n\n"); + fprintf(stderr, "Interface assignment:\n"); + fprintf(stderr, " 0..n assignments like =\n\n"); + fprintf(stderr, " e.g. vcan2=can0 (send frames received from can0 on " + "vcan2)\n"); + fprintf(stderr, " extra hook: stdout=can0 (print logfile line marked with can0 on " + "stdout)\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 " "timestamp) are ignored.\n\n"); } @@ -357,7 +359,7 @@ int main(int argc, char **argv) return 1; } strcpy(buf, argv[optind+i]); - for (j=0; j#R{len} for 'classic' CAN 2.0 data frames\n"); + fprintf(stderr, " ##{data} for CAN FD frames\n\n"); + fprintf(stderr, ":\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, ":\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 s; /* can raw socket */ @@ -68,27 +91,15 @@ int main(int argc, char **argv) /* check command line options */ if (argc != 3) { - fprintf(stderr, "Usage: %s .\n", argv[0]); + print_usage(argv[0]); return 1; } /* parse CAN frame */ required_mtu = parse_canframe(argv[2], &frame); if (!required_mtu){ - fprintf(stderr, "\nWrong CAN-frame format! Try:\n\n"); - fprintf(stderr, " #{data} for 'classic' CAN 2.0 data frames\n"); - fprintf(stderr, " #R{len} for 'classic' CAN 2.0 RTR frames\n"); - fprintf(stderr, " ##{data} for CAN FD frames\n\n"); - fprintf(stderr, " 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, " 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"); + fprintf(stderr, "\nWrong CAN-frame format!\n\n"); + print_usage(argv[0]); return 1; } @@ -110,7 +121,7 @@ int main(int argc, char **argv) addr.can_family = AF_CAN; 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 */ if (ioctl(s, SIOCGIFMTU, &ifr) < 0) { diff --git a/cansniffer.c b/cansniffer.c index 0ff29b4..90d8d75 100644 --- a/cansniffer.c +++ b/cansniffer.c @@ -1,6 +1,6 @@ /* 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 * All rights reserved. @@ -44,6 +44,8 @@ #include #include +#include +#include #include #include #include @@ -61,13 +63,14 @@ #include #include -#include +#include #include #include "terminal.h" #define SETFNAME "sniffset." #define ANYDEV "any" +#define MAX_SLOTS 2048 /* flags */ @@ -92,9 +95,10 @@ #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; long hold; long timeout; @@ -104,75 +108,118 @@ struct snif { struct can_frame current; struct can_frame marker; struct can_frame notch; -} sniftab[2048]; - +} sniftab[MAX_SLOTS]; extern int optind, opterr, optopt; +static int idx; static int running = 1; static int clearscreen = 1; +static int print_eff; static int notch; -static int filter_id_only; static long timeout = TIMEOUT; static long hold = HOLD; static long loop = LOOP; static unsigned char binary; +static unsigned char binary8; static unsigned char binary_gap; static unsigned char color; static char *interface; +static char *vdl = LDL; /* variable delimiter */ +static char *ldl = LDL; /* long delimiter */ -void rx_setup (int fd, int id); -void rx_delete (int fd, int id); -void print_snifline(int id); -int handle_keyb(int fd); -int handle_bcm(int fd, long currcms); -int handle_timeo(int fd, long currcms); +void print_snifline(int slot); +int handle_keyb(void); +int handle_frame(int fd, long currcms); +int handle_timeo(long currcms); 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) { const char manual [] = { "commands that can be entered at runtime:\n" - "\n" - "q - quit\n" - "b - toggle binary / HEX-ASCII output\n" - "B - toggle binary with gap / HEX-ASCII output (exceeds 80 chars!)\n" - "c - toggle color mode\n" - "# - notch currently marked/changed bits (can be used repeatedly)\n" - "* - clear notched marked\n" - "rMYNAME - read settings file (filter/notch)\n" - "wMYNAME - write settings file (filter/notch)\n" - "+FILTER - add CAN-IDs to sniff\n" - "-FILTER - remove CAN-IDs to sniff\n" + " q - quit\n" + " b - toggle binary / HEX-ASCII output\n" + " 8 - toggle binary / HEX-ASCII output (small for EFF on 80 chars)\n" + " B - toggle binary with gap / HEX-ASCII output (exceeds 80 chars!)\n" + " c - toggle color mode\n" + " - force a clear screen\n" + " # - notch currently marked/changed bits (can be used repeatedly)\n" + " * - clear notched marked\n" + " rMYNAME - read settings file (filter/notch)\n" + " wMYNAME - write settings file (filter/notch)\n" + " a - enable 'a'll SFF CAN-IDs to sniff\n" + " n - enable 'n'one SFF CAN-IDs to sniff\n" + " A - enable 'A'll EFF CAN-IDs to sniff\n" + " N - enable 'N'one EFF CAN-IDs to sniff\n" + " +FILTER - add CAN-IDs to sniff\n" + " -FILTER - remove CAN-IDs to sniff\n" "\n" "FILTER can be a single CAN-ID or a CAN-ID/Bitmask:\n" - "+1F5 - add CAN-ID 0x1F5\n" - "-42E - remove CAN-ID 0x42E\n" - "-42E7FF - remove CAN-ID 0x42E (using Bitmask)\n" - "-500700 - remove CAN-IDs 0x500 - 0x5FF\n" - "+400600 - add CAN-IDs 0x400 - 0x5FF\n" - "+000000 - add all CAN-IDs\n" - "-000000 - remove all CAN-IDs\n" + "\n" + " single SFF 11 bit IDs:\n" + " +1F5 - add SFF CAN-ID 0x1F5\n" + " -42E - remove SFF CAN-ID 0x42E\n" + "\n" + " single EFF 29 bit IDs:\n" + " +18FEDF55 - add EFF CAN-ID 0x18FEDF55\n" + " -00000090 - remove EFF CAN-ID 0x00000090\n" + "\n" + " CAN-ID/Bitmask SFF:\n" + " -42E7FF - remove SFF CAN-ID 0x42E (using Bitmask)\n" + " -500700 - remove SFF CAN-IDs 0x500 - 0x5FF\n" + " +400600 - add SFF CAN-IDs 0x400 - 0x5FF\n" + " +000000 - add all SFF CAN-IDs\n" + " -000000 - remove all SFF CAN-IDs\n" + "\n" + " CAN-ID/Bitmask EFF:\n" + " -0000000000000000 - remove all EFF CAN-IDs\n" + " +12345678000000FF - add EFF CAN IDs xxxxxx78\n" + " +0000000000000000 - add all EFF CAN-IDs\n" "\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" }; + fprintf(stderr, "%s - volatile CAN content visualizer.\n", prg); fprintf(stderr, "\nUsage: %s [can-interface]\n", prg); - fprintf(stderr, "Options: -m (initial FILTER default 0x00000000)\n"); - fprintf(stderr, " -v (initial FILTER default 0x00000000)\n"); - fprintf(stderr, " -q (quiet - all IDs deactivated)\n"); - fprintf(stderr, " -r (read %sname from file)\n", SETFNAME); - fprintf(stderr, " -b (start with binary mode)\n"); - fprintf(stderr, " -B (start with binary mode with gap - exceeds 80 chars!)\n"); - fprintf(stderr, " -c (color changes)\n"); - fprintf(stderr, " -f (filter on CAN-ID only)\n"); - fprintf(stderr, " -t