Compare commits
26 Commits
2638b3965c
...
3fabeb6a52
| Author | SHA1 | Date |
|---|---|---|
|
|
3fabeb6a52 | |
|
|
fafeedec1e | |
|
|
e8559479fb | |
|
|
6050aa155d | |
|
|
302184f383 | |
|
|
c542c9ada7 | |
|
|
2b8c7c5f4b | |
|
|
4577316bd6 | |
|
|
4364d655b8 | |
|
|
2e71e396c5 | |
|
|
01083a64eb | |
|
|
008f9f8e22 | |
|
|
66e7c08beb | |
|
|
4b66e8c56f | |
|
|
e6e3253972 | |
|
|
6d69bef837 | |
|
|
4d8b247258 | |
|
|
0e9c53f6d3 | |
|
|
99c5c14790 | |
|
|
df8e08fa70 | |
|
|
cb5ab07f34 | |
|
|
0e692bf42e | |
|
|
0984817438 | |
|
|
b3da2f62b9 | |
|
|
b85418d75c | |
|
|
6eb97b57c5 |
|
|
@ -30,7 +30,10 @@ jobs:
|
||||||
podman run --name stable -di --userns=keep-id:uid=1000,gid=1000 -v "$PWD":/home -w /home ${{ matrix.release }} bash
|
podman run --name stable -di --userns=keep-id:uid=1000,gid=1000 -v "$PWD":/home -w /home ${{ matrix.release }} bash
|
||||||
podman exec -i stable uname -a
|
podman exec -i stable uname -a
|
||||||
podman exec -i stable id
|
podman exec -i stable id
|
||||||
|
podman exec -i -u root stable dpkg --add-architecture arm64
|
||||||
|
podman exec -i -u root stable dpkg --add-architecture armhf
|
||||||
podman exec -i -u root stable apt update
|
podman exec -i -u root stable apt update
|
||||||
|
podman exec -e DEBIAN_FRONTEND='noninteractive' -i -u root stable apt upgrade -o APT::Install-Suggests=false -qy
|
||||||
podman exec -e DEBIAN_FRONTEND='noninteractive' -i -u root stable apt install -o APT::Install-Suggests=false -qy ${release} \
|
podman exec -e DEBIAN_FRONTEND='noninteractive' -i -u root stable apt install -o APT::Install-Suggests=false -qy ${release} \
|
||||||
clang \
|
clang \
|
||||||
cmake \
|
cmake \
|
||||||
|
|
@ -38,27 +41,30 @@ jobs:
|
||||||
gcc-aarch64-linux-gnu \
|
gcc-aarch64-linux-gnu \
|
||||||
gcc-arm-linux-gnueabihf \
|
gcc-arm-linux-gnueabihf \
|
||||||
gcc-mips-linux-gnu \
|
gcc-mips-linux-gnu \
|
||||||
|
libgps-dev \
|
||||||
|
libgps-dev:arm64 \
|
||||||
|
libgps-dev:armhf \
|
||||||
make
|
make
|
||||||
|
|
||||||
- name: Configure & Build with gcc
|
- name: Configure & Build with gcc
|
||||||
env:
|
env:
|
||||||
cc: gcc
|
cc: gcc
|
||||||
run: |
|
run: |
|
||||||
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=${cc} -DENABLE_WERROR=ON -B build-${cc}
|
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=${cc} -DENABLE_WERROR=ON -DENABLE_GPS=ON -B build-${cc}
|
||||||
podman exec -i stable cmake --build build-${cc}
|
podman exec -i stable cmake --build build-${cc}
|
||||||
|
|
||||||
- name: Configure & Build with clang
|
- name: Configure & Build with clang
|
||||||
env:
|
env:
|
||||||
cc: clang
|
cc: clang
|
||||||
run: |
|
run: |
|
||||||
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=${cc} -DENABLE_WERROR=ON -B build-${cc}
|
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=${cc} -DENABLE_WERROR=ON -DENABLE_GPS=ON -B build-${cc}
|
||||||
podman exec -i stable cmake --build build-${cc}
|
podman exec -i stable cmake --build build-${cc}
|
||||||
|
|
||||||
- name: Configure & Build with arm-linux-gnueabihf-gcc
|
- name: Configure & Build with arm-linux-gnueabihf-gcc
|
||||||
env:
|
env:
|
||||||
toolchain: arm-linux-gnueabihf-gcc
|
toolchain: arm-linux-gnueabihf-gcc
|
||||||
run: |
|
run: |
|
||||||
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=cmake/${toolchain}.cmake -DENABLE_WERROR=ON -B build-${toolchain}
|
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=cmake/${toolchain}.cmake -DENABLE_WERROR=ON -DENABLE_GPS=ON -B build-${toolchain}
|
||||||
podman exec -i stable cmake --build build-${toolchain}
|
podman exec -i stable cmake --build build-${toolchain}
|
||||||
|
|
||||||
- name: Configure & Build with arm-linux-gnueabihf-clang
|
- name: Configure & Build with arm-linux-gnueabihf-clang
|
||||||
|
|
@ -67,14 +73,14 @@ jobs:
|
||||||
env:
|
env:
|
||||||
toolchain: arm-linux-gnueabihf-clang
|
toolchain: arm-linux-gnueabihf-clang
|
||||||
run: |
|
run: |
|
||||||
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=cmake/${toolchain}.cmake -DENABLE_WERROR=ON -B build-${toolchain}
|
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=cmake/${toolchain}.cmake -DENABLE_WERROR=ON -DENABLE_GPS=ON -B build-${toolchain}
|
||||||
podman exec -i stable cmake --build build-${toolchain}
|
podman exec -i stable cmake --build build-${toolchain}
|
||||||
|
|
||||||
- name: Configure & Build with aarch64-linux-gnu-gcc
|
- name: Configure & Build with aarch64-linux-gnu-gcc
|
||||||
env:
|
env:
|
||||||
toolchain: aarch64-linux-gnu-gcc
|
toolchain: aarch64-linux-gnu-gcc
|
||||||
run: |
|
run: |
|
||||||
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=cmake/${toolchain}.cmake -DENABLE_WERROR=ON -B build-${toolchain}
|
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=cmake/${toolchain}.cmake -DENABLE_WERROR=ON -DENABLE_GPS=ON -B build-${toolchain}
|
||||||
podman exec -i stable cmake --build build-${toolchain}
|
podman exec -i stable cmake --build build-${toolchain}
|
||||||
|
|
||||||
- name: Configure & Build with aarch64-linux-gnu-clang
|
- name: Configure & Build with aarch64-linux-gnu-clang
|
||||||
|
|
@ -83,7 +89,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
toolchain: aarch64-linux-gnu-clang
|
toolchain: aarch64-linux-gnu-clang
|
||||||
run: |
|
run: |
|
||||||
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=cmake/${toolchain}.cmake -DENABLE_WERROR=ON -B build-${toolchain}
|
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=cmake/${toolchain}.cmake -DENABLE_WERROR=ON -DENABLE_GPS=ON -B build-${toolchain}
|
||||||
podman exec -i stable cmake --build build-${toolchain}
|
podman exec -i stable cmake --build build-${toolchain}
|
||||||
|
|
||||||
- name: Configure & Build with mips-linux-gnu-gcc
|
- name: Configure & Build with mips-linux-gnu-gcc
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,12 @@
|
||||||
*~
|
*~
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
*.o
|
*.o
|
||||||
.ccls-cache
|
.ccls-cache
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles/
|
||||||
|
cmake_install.cmake
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
tags
|
tags
|
||||||
/build
|
/build
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,12 @@ endif()
|
||||||
|
|
||||||
# Add an option to enable treating warnings as errors
|
# Add an option to enable treating warnings as errors
|
||||||
option(ENABLE_WERROR "Treat all compiler warnings as errors" OFF)
|
option(ENABLE_WERROR "Treat all compiler warnings as errors" OFF)
|
||||||
|
option(ENABLE_GPS "Enable GPS support" OFF)
|
||||||
|
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
if(ENABLE_GPS)
|
||||||
|
pkg_check_modules(GPS REQUIRED libgps)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(ENABLE_WERROR)
|
if(ENABLE_WERROR)
|
||||||
add_compile_options(-Werror)
|
add_compile_options(-Werror)
|
||||||
|
|
@ -67,6 +73,10 @@ set(PROGRAMS_J1939_TIMEDATE
|
||||||
j1939-timedate-cli
|
j1939-timedate-cli
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(PROGRAMS_J1939_VEHICLE_POSITION
|
||||||
|
j1939-vehicle-position-srv
|
||||||
|
)
|
||||||
|
|
||||||
set(PROGRAMS_ISOBUSFS
|
set(PROGRAMS_ISOBUSFS
|
||||||
isobusfs-srv
|
isobusfs-srv
|
||||||
isobusfs-cli
|
isobusfs-cli
|
||||||
|
|
@ -126,6 +136,7 @@ if(NOT ANDROID)
|
||||||
|
|
||||||
set_target_properties(isobusfs PROPERTIES
|
set_target_properties(isobusfs PROPERTIES
|
||||||
PUBLIC_HEADER "${PUBLIC_HEADER_ISOBUSFS}"
|
PUBLIC_HEADER "${PUBLIC_HEADER_ISOBUSFS}"
|
||||||
|
SOVERSION 0
|
||||||
)
|
)
|
||||||
|
|
||||||
install(TARGETS isobusfs
|
install(TARGETS isobusfs
|
||||||
|
|
@ -190,6 +201,24 @@ if(NOT ANDROID)
|
||||||
j1939-timedate-srv
|
j1939-timedate-srv
|
||||||
DESTINATION ${CMAKE_INSTALL_BINDIR})
|
DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
|
||||||
|
if(ENABLE_GPS)
|
||||||
|
set(PUBLIC_HEADER_J1939_VEHICLE_POSITION
|
||||||
|
j1939_vehicle_position/j1939_vehicle_position_cmn.h
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(j1939-vehicle-position-srv
|
||||||
|
j1939_vehicle_position/j1939_vehicle_position_srv.c
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(j1939-vehicle-position-srv
|
||||||
|
PRIVATE can j1939 ${GPS_LIBRARIES}
|
||||||
|
)
|
||||||
|
|
||||||
|
install(TARGETS
|
||||||
|
j1939-vehicle-position-srv
|
||||||
|
DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_library(can STATIC
|
add_library(can STATIC
|
||||||
|
|
|
||||||
15
Makefile
15
Makefile
|
|
@ -67,6 +67,9 @@ PROGRAMS_J1939_TIMEDATE := \
|
||||||
j1939-timedate-srv \
|
j1939-timedate-srv \
|
||||||
j1939-timedate-cli
|
j1939-timedate-cli
|
||||||
|
|
||||||
|
PROGRAMS_J1939_VEHICLE_POSITION := \
|
||||||
|
j1939-vehicle-position-srv
|
||||||
|
|
||||||
PROGRAMS_ISOBUSFS := \
|
PROGRAMS_ISOBUSFS := \
|
||||||
isobusfs-srv \
|
isobusfs-srv \
|
||||||
isobusfs-cli
|
isobusfs-cli
|
||||||
|
|
@ -98,6 +101,7 @@ PROGRAMS_SLCAN := \
|
||||||
PROGRAMS := \
|
PROGRAMS := \
|
||||||
$(PROGRAMS_CANGW) \
|
$(PROGRAMS_CANGW) \
|
||||||
$(PROGRAMS_J1939_TIMEDATE) \
|
$(PROGRAMS_J1939_TIMEDATE) \
|
||||||
|
$(PROGRAMS_J1939_VEHICLE_POSITION) \
|
||||||
$(PROGRAMS_ISOBUSFS) \
|
$(PROGRAMS_ISOBUSFS) \
|
||||||
$(PROGRAMS_ISOTP) \
|
$(PROGRAMS_ISOTP) \
|
||||||
$(PROGRAMS_J1939) \
|
$(PROGRAMS_J1939) \
|
||||||
|
|
@ -126,7 +130,8 @@ endif
|
||||||
all: $(PROGRAMS)
|
all: $(PROGRAMS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(PROGRAMS) *.o mcp251xfd/*.o isobusfs/*.o j1939_timedate/*.o
|
rm -f $(PROGRAMS) *.o mcp251xfd/*.o isobusfs/*.o j1939_timedate/*.o \
|
||||||
|
j1939_vehicle_position/*.o
|
||||||
|
|
||||||
install:
|
install:
|
||||||
mkdir -p $(DESTDIR)$(PREFIX)/bin
|
mkdir -p $(DESTDIR)$(PREFIX)/bin
|
||||||
|
|
@ -153,6 +158,8 @@ isobusfs_srv.o: lib.h libj1939.h
|
||||||
isobusfs_c.o: lib.h libj1939.h
|
isobusfs_c.o: lib.h libj1939.h
|
||||||
j1939_timedate_srv.o: lib.h libj1939.h
|
j1939_timedate_srv.o: lib.h libj1939.h
|
||||||
j1939_timedate_cli.o: lib.h libj1939.h
|
j1939_timedate_cli.o: lib.h libj1939.h
|
||||||
|
j1939_vehicle_position_srv.o: lib.h libj1939.h
|
||||||
|
|
||||||
canframelen.o: canframelen.h
|
canframelen.o: canframelen.h
|
||||||
|
|
||||||
asc2log: asc2log.o lib.o
|
asc2log: asc2log.o lib.o
|
||||||
|
|
@ -182,6 +189,12 @@ j1939-timedate-cli: lib.o \
|
||||||
j1939_timedate/j1939_timedate_cli.o
|
j1939_timedate/j1939_timedate_cli.o
|
||||||
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
|
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
|
||||||
|
|
||||||
|
j1939-vehicle-position-srv: \
|
||||||
|
lib.o \
|
||||||
|
libj1939.o \
|
||||||
|
j1939_vehicle_position/j1939_vehicle_position_srv.o \
|
||||||
|
$(CC) $(LDFLAGS) $^ $(LDLIBS) -lgps -o $@
|
||||||
|
|
||||||
isobusfs-srv: lib.o \
|
isobusfs-srv: lib.o \
|
||||||
libj1939.o \
|
libj1939.o \
|
||||||
isobusfs/isobusfs_cmn.o \
|
isobusfs/isobusfs_cmn.o \
|
||||||
|
|
|
||||||
571
asc2log.c
571
asc2log.c
|
|
@ -58,7 +58,17 @@
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
|
|
||||||
#define BUFLEN 400 /* CAN FD mode lines can be pretty long */
|
#define BUFLEN 6500 /* CAN XL mode lines can be pretty long */
|
||||||
|
#define NO_DIR '.'
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
#define ASC_F_XLF 0x00400000
|
||||||
|
#define ASC_F_RES 0x00800000
|
||||||
|
#define ASC_F_SEC 0x01000000
|
||||||
|
|
||||||
extern int optind, opterr, optopt;
|
extern int optind, opterr, optopt;
|
||||||
|
|
||||||
|
|
@ -69,10 +79,12 @@ static void print_usage(char *prg)
|
||||||
fprintf(stderr, "Options:\n");
|
fprintf(stderr, "Options:\n");
|
||||||
fprintf(stderr, "\t-I <infile>\t(default stdin)\n");
|
fprintf(stderr, "\t-I <infile>\t(default stdin)\n");
|
||||||
fprintf(stderr, "\t-O <outfile>\t(default stdout)\n");
|
fprintf(stderr, "\t-O <outfile>\t(default stdout)\n");
|
||||||
|
fprintf(stderr, "\t-d (disable direction information R/T)\n");
|
||||||
|
fprintf(stderr, "\t-v (verbose)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void prframe(FILE *file, struct timeval *tv, int dev,
|
static void prframe(FILE *file, struct timeval *tv, int dev,
|
||||||
struct canfd_frame *cf, char *extra_info)
|
cu_t *cf, char dir)
|
||||||
{
|
{
|
||||||
static char abuf[BUFLEN];
|
static char abuf[BUFLEN];
|
||||||
|
|
||||||
|
|
@ -83,19 +95,23 @@ static void prframe(FILE *file, struct timeval *tv, int dev,
|
||||||
else
|
else
|
||||||
fprintf(file, "canX ");
|
fprintf(file, "canX ");
|
||||||
|
|
||||||
snprintf_canframe(abuf, sizeof(abuf), (cu_t *)cf, 0);
|
snprintf_canframe(abuf, sizeof(abuf), cf, 0);
|
||||||
fprintf(file, "%s%s", abuf, extra_info);
|
|
||||||
|
if (dir == NO_DIR)
|
||||||
|
fprintf(file, "%s\n", abuf);
|
||||||
|
else
|
||||||
|
fprintf(file, "%s %c\n", abuf, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_can_id(struct canfd_frame *cf, char *idstring, int base)
|
static void get_can_id(canid_t *can_id, char *idstring, int base)
|
||||||
{
|
{
|
||||||
if (idstring[strlen(idstring)-1] == 'x') {
|
if (idstring[strlen(idstring)-1] == 'x') {
|
||||||
cf->can_id = CAN_EFF_FLAG;
|
*can_id = CAN_EFF_FLAG;
|
||||||
idstring[strlen(idstring)-1] = 0;
|
idstring[strlen(idstring)-1] = 0;
|
||||||
} else
|
} else
|
||||||
cf->can_id = 0;
|
*can_id = 0;
|
||||||
|
|
||||||
cf->can_id |= strtoul(idstring, NULL, base);
|
*can_id |= strtoul(idstring, NULL, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void calc_tv(struct timeval *tv, struct timeval *read_tv,
|
static void calc_tv(struct timeval *tv, struct timeval *read_tv,
|
||||||
|
|
@ -131,7 +147,7 @@ static void calc_tv(struct timeval *tv, struct timeval *read_tv,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void eval_can(char* buf, struct timeval *date_tvp, char timestamps,
|
static void eval_can(char* buf, struct timeval *date_tvp, char timestamps,
|
||||||
char base, int dplace, FILE *outfile)
|
char base, int dplace, int disable_dir, FILE *outfile)
|
||||||
{
|
{
|
||||||
int interface;
|
int interface;
|
||||||
static struct timeval tv; /* current frame timestamp */
|
static struct timeval tv; /* current frame timestamp */
|
||||||
|
|
@ -142,27 +158,26 @@ static void eval_can(char* buf, struct timeval *date_tvp, char timestamps,
|
||||||
int dlc = 0;
|
int dlc = 0;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int data[8];
|
int data[8];
|
||||||
char tmp1[BUFLEN];
|
char idstr[21];
|
||||||
char dir[3]; /* 'Rx' or 'Tx' plus terminating zero */
|
char dir[5]; /* 'Rx'/'Tx'/'TxRq' plus terminating zero */
|
||||||
char *extra_info;
|
|
||||||
int i, items;
|
int i, items;
|
||||||
unsigned long long sec, usec;
|
unsigned long long sec, usec;
|
||||||
|
|
||||||
/* check for ErrorFrames */
|
/* check for ErrorFrames */
|
||||||
if (sscanf(buf, "%llu.%llu %d %s",
|
if (sscanf(buf, "%llu.%llu %d %20s",
|
||||||
&sec, &usec,
|
&sec, &usec,
|
||||||
&interface, tmp1) == 4) {
|
&interface, idstr) == 4) {
|
||||||
read_tv.tv_sec = sec;
|
read_tv.tv_sec = sec;
|
||||||
read_tv.tv_usec = usec;
|
read_tv.tv_usec = usec;
|
||||||
|
|
||||||
if (!strncmp(tmp1, "ErrorFrame", strlen("ErrorFrame"))) {
|
if (!strncmp(idstr, "ErrorFrame", strlen("ErrorFrame"))) {
|
||||||
|
|
||||||
/* do not know more than 'Error' */
|
/* do not know more than 'Error' */
|
||||||
cf.can_id = (CAN_ERR_FLAG | CAN_ERR_BUSERROR);
|
cf.can_id = (CAN_ERR_FLAG | CAN_ERR_BUSERROR);
|
||||||
cf.len = CAN_ERR_DLC;
|
cf.len = CAN_ERR_DLC;
|
||||||
|
|
||||||
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
||||||
prframe(outfile, &tv, interface, &cf, "\n");
|
prframe(outfile, &tv, interface, (cu_t *)&cf, NO_DIR);
|
||||||
fflush(outfile);
|
fflush(outfile);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -172,15 +187,15 @@ static void eval_can(char* buf, struct timeval *date_tvp, char timestamps,
|
||||||
|
|
||||||
/* check for CAN frames with (hexa)decimal values */
|
/* check for CAN frames with (hexa)decimal values */
|
||||||
if (base == 'h')
|
if (base == 'h')
|
||||||
items = sscanf(buf, "%llu.%llu %d %s %2s %c %x %x %x %x %x %x %x %x %x",
|
items = sscanf(buf, "%llu.%llu %d %20s %4s %c %x %x %x %x %x %x %x %x %x",
|
||||||
&sec, &usec, &interface,
|
&sec, &usec, &interface,
|
||||||
tmp1, dir, &rtr, &dlc,
|
idstr, dir, &rtr, &dlc,
|
||||||
&data[0], &data[1], &data[2], &data[3],
|
&data[0], &data[1], &data[2], &data[3],
|
||||||
&data[4], &data[5], &data[6], &data[7]);
|
&data[4], &data[5], &data[6], &data[7]);
|
||||||
else
|
else
|
||||||
items = sscanf(buf, "%llu.%llu %d %s %2s %c %x %d %d %d %d %d %d %d %d",
|
items = sscanf(buf, "%llu.%llu %d %20s %4s %c %x %d %d %d %d %d %d %d %d",
|
||||||
&sec, &usec, &interface,
|
&sec, &usec, &interface,
|
||||||
tmp1, dir, &rtr, &dlc,
|
idstr, dir, &rtr, &dlc,
|
||||||
&data[0], &data[1], &data[2], &data[3],
|
&data[0], &data[1], &data[2], &data[3],
|
||||||
&data[4], &data[5], &data[6], &data[7]);
|
&data[4], &data[5], &data[6], &data[7]);
|
||||||
|
|
||||||
|
|
@ -205,9 +220,9 @@ static void eval_can(char* buf, struct timeval *date_tvp, char timestamps,
|
||||||
|
|
||||||
/* check for CAN ID with (hexa)decimal value */
|
/* check for CAN ID with (hexa)decimal value */
|
||||||
if (base == 'h')
|
if (base == 'h')
|
||||||
get_can_id(&cf, tmp1, 16);
|
get_can_id(&cf.can_id, idstr, 16);
|
||||||
else
|
else
|
||||||
get_can_id(&cf, tmp1, 10);
|
get_can_id(&cf.can_id, idstr, 10);
|
||||||
|
|
||||||
/* dlc > 8 => len == CAN_MAX_DLEN => fill len8_dlc value */
|
/* dlc > 8 => len == CAN_MAX_DLEN => fill len8_dlc value */
|
||||||
if (dlc > CAN_MAX_DLC)
|
if (dlc > CAN_MAX_DLC)
|
||||||
|
|
@ -216,6 +231,9 @@ static void eval_can(char* buf, struct timeval *date_tvp, char timestamps,
|
||||||
if (strlen(dir) != 2) /* "Rx" or "Tx" */
|
if (strlen(dir) != 2) /* "Rx" or "Tx" */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (disable_dir)
|
||||||
|
dir[0] = NO_DIR;
|
||||||
|
|
||||||
/* check for signed integer overflow */
|
/* check for signed integer overflow */
|
||||||
if (dplace == 4 && read_tv.tv_usec >= INT_MAX / 100)
|
if (dplace == 4 && read_tv.tv_usec >= INT_MAX / 100)
|
||||||
return;
|
return;
|
||||||
|
|
@ -223,11 +241,6 @@ static void eval_can(char* buf, struct timeval *date_tvp, char timestamps,
|
||||||
if (dplace == 5 && read_tv.tv_usec >= INT_MAX / 10)
|
if (dplace == 5 && read_tv.tv_usec >= INT_MAX / 10)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (dir[0] == 'R')
|
|
||||||
extra_info = " R\n";
|
|
||||||
else
|
|
||||||
extra_info = " T\n";
|
|
||||||
|
|
||||||
cf.len = len;
|
cf.len = len;
|
||||||
if (rtr == 'r')
|
if (rtr == 'r')
|
||||||
cf.can_id |= CAN_RTR_FLAG;
|
cf.can_id |= CAN_RTR_FLAG;
|
||||||
|
|
@ -236,13 +249,13 @@ static void eval_can(char* buf, struct timeval *date_tvp, char timestamps,
|
||||||
cf.data[i] = data[i] & 0xFFU;
|
cf.data[i] = data[i] & 0xFFU;
|
||||||
|
|
||||||
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
||||||
prframe(outfile, &tv, interface, &cf, extra_info);
|
prframe(outfile, &tv, interface, (cu_t *)&cf, dir[0]);
|
||||||
fflush(outfile);
|
fflush(outfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps,
|
static void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps,
|
||||||
int dplace, FILE *outfile)
|
int dplace, int disable_dir, FILE *outfile)
|
||||||
{
|
{
|
||||||
int interface;
|
int interface;
|
||||||
static struct timeval tv; /* current frame timestamp */
|
static struct timeval tv; /* current frame timestamp */
|
||||||
|
|
@ -251,29 +264,33 @@ static void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps,
|
||||||
unsigned char brs, esi, ctmp;
|
unsigned char brs, esi, ctmp;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
int dlc, dlen = 0;
|
int dlc, dlen = 0;
|
||||||
char tmp1[BUFLEN];
|
char idstr[21];
|
||||||
char dir[3]; /* 'Rx' or 'Tx' plus terminating zero */
|
char dir[5]; /* 'Rx'/'Tx'/'TxRq' plus terminating zero */
|
||||||
char *extra_info;
|
|
||||||
char *ptr;
|
char *ptr;
|
||||||
int i;
|
int i;
|
||||||
|
int n = 0; /* sscanf consumed characters */
|
||||||
unsigned long long sec, usec;
|
unsigned long long sec, usec;
|
||||||
|
|
||||||
/* The CANFD format is mainly in hex representation but <DataLength>
|
/*
|
||||||
and probably some content we skip anyway. Don't trust the docs! */
|
* 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 \
|
* 21.671796 CANFD 1 Tx 11 msgCanFdFr1 1 0 a 16 \
|
||||||
100000 214 223040 80000000 46500250 460a0250 20011736 20010205 */
|
* 00 00 00 00 00 00 00 00 00 00 00 00 00 00 59 c0 \
|
||||||
|
* 100000 214 223040 80000000 46500250 460a0250 20011736 20010205
|
||||||
|
*/
|
||||||
|
|
||||||
/* check for valid line without symbolic name */
|
/* check for valid line without symbolic name */
|
||||||
if (sscanf(buf, "%llu.%llu %*s %d %2s %s %hhx %hhx %x %d ",
|
if (sscanf(buf, "%llu.%llu %*s %d %4s %20s %hhx %hhx %x %d %n",
|
||||||
&sec, &usec, &interface,
|
&sec, &usec, &interface,
|
||||||
dir, tmp1, &brs, &esi, &dlc, &dlen) != 9) {
|
dir, idstr, &brs, &esi, &dlc, &dlen, &n) != 9) {
|
||||||
|
|
||||||
/* check for valid line with a symbolic name */
|
/* check for valid line with a symbolic name */
|
||||||
if (sscanf(buf, "%llu.%llu %*s %d %2s %s %*s %hhx %hhx %x %d ",
|
if (sscanf(buf, "%llu.%llu %*s %d %4s %20s %*s %hhx %hhx %x %d %n",
|
||||||
&sec, &usec, &interface,
|
&sec, &usec, &interface,
|
||||||
dir, tmp1, &brs, &esi, &dlc, &dlen) != 9) {
|
dir, idstr, &brs, &esi, &dlc, &dlen, &n) != 9) {
|
||||||
|
|
||||||
/* no valid CANFD format pattern */
|
/* no valid CANFD format pattern */
|
||||||
return;
|
return;
|
||||||
|
|
@ -290,6 +307,9 @@ static void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps,
|
||||||
if (strlen(dir) != 2) /* "Rx" or "Tx" */
|
if (strlen(dir) != 2) /* "Rx" or "Tx" */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (disable_dir)
|
||||||
|
dir[0] = NO_DIR;
|
||||||
|
|
||||||
/* check for signed integer overflow */
|
/* check for signed integer overflow */
|
||||||
if (dplace == 4 && read_tv.tv_usec >= INT_MAX / 100)
|
if (dplace == 4 && read_tv.tv_usec >= INT_MAX / 100)
|
||||||
return;
|
return;
|
||||||
|
|
@ -298,26 +318,13 @@ static void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps,
|
||||||
if (dplace == 5 && read_tv.tv_usec >= INT_MAX / 10)
|
if (dplace == 5 && read_tv.tv_usec >= INT_MAX / 10)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (dir[0] == 'R')
|
|
||||||
extra_info = " R\n";
|
|
||||||
else
|
|
||||||
extra_info = " T\n";
|
|
||||||
|
|
||||||
/* don't trust ASCII content - sanitize data length */
|
/* don't trust ASCII content - sanitize data length */
|
||||||
if (dlen != can_fd_dlc2len(can_fd_len2dlc(dlen)))
|
if (dlen != can_fd_dlc2len(can_fd_len2dlc(dlen)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
get_can_id(&cf, tmp1, 16);
|
get_can_id(&cf.can_id, idstr, 16);
|
||||||
|
|
||||||
/* now search for the beginning of the data[] content */
|
ptr = buf + n; /* start of ASCII hex frame data */
|
||||||
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;
|
cf.len = dlen;
|
||||||
|
|
||||||
|
|
@ -341,12 +348,6 @@ static void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps,
|
||||||
if (sscanf(ptr, " %*x %*x %x ", &flags) != 1)
|
if (sscanf(ptr, " %*x %*x %x ", &flags) != 1)
|
||||||
return;
|
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) {
|
if (flags & ASC_F_FDF) {
|
||||||
cf.flags = CANFD_FDF;
|
cf.flags = CANFD_FDF;
|
||||||
if (flags & ASC_F_BRS)
|
if (flags & ASC_F_BRS)
|
||||||
|
|
@ -373,12 +374,408 @@ static void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps,
|
||||||
}
|
}
|
||||||
|
|
||||||
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
||||||
prframe(outfile, &tv, interface, &cf, extra_info);
|
prframe(outfile, &tv, interface, (cu_t *)&cf, dir[0]);
|
||||||
fflush(outfile);
|
fflush(outfile);
|
||||||
|
|
||||||
/* No support for really strange CANFD ErrorFrames format m( */
|
/* No support for really strange CANFD ErrorFrames format m( */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void eval_canxl_cc(char* buf, struct timeval *date_tvp, char timestamps,
|
||||||
|
int dplace, int disable_dir, FILE *outfile)
|
||||||
|
{
|
||||||
|
int interface;
|
||||||
|
static struct timeval tv; /* current frame timestamp */
|
||||||
|
static struct timeval read_tv; /* frame timestamp from ASC file */
|
||||||
|
struct can_frame cf = { 0 };
|
||||||
|
unsigned char ctmp;
|
||||||
|
unsigned int flags;
|
||||||
|
int dlc, dlen = 0;
|
||||||
|
char idstr[21];
|
||||||
|
char dir[5]; /* 'Rx'/'Tx'/'TxRq' plus terminating zero */
|
||||||
|
char *ptr;
|
||||||
|
int i;
|
||||||
|
int n = 0; /* sscanf consumed characters */
|
||||||
|
unsigned long long sec, usec;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 59.171614 CANXL 2 Rx CBFF 243215 176 432 msgCanCCTest1 \
|
||||||
|
* f 8 e1 89 e8 c2 b9 6d 5a f1 174 00000000 00000000 \
|
||||||
|
* 000000050005000e 0000000000a00010 0000000a000a001d \
|
||||||
|
* 0000000000a00002 000000100010000f 000000000a00001
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* check for valid line without symbolic name */
|
||||||
|
if (sscanf(buf,
|
||||||
|
"%llu.%llu %*s %d %4s " /* time, CANXL, channel, direction */
|
||||||
|
"%*s %*s %*s %20s " /* frame format, msg dur, bit count, ID */
|
||||||
|
"%x %d %n", /* DLC, Datalen */
|
||||||
|
&sec, &usec, &interface, dir,
|
||||||
|
idstr,
|
||||||
|
&dlc, &dlen, &n) != 7) {
|
||||||
|
/* check for valid line with a symbolic name */
|
||||||
|
if (sscanf(buf,
|
||||||
|
"%llu.%llu %*s %d %4s " /* time, CANXL, channel, direction */
|
||||||
|
"%*s %*s %*s %20s " /* frame format, msg dur, bit count, ID */
|
||||||
|
"%*s %x %d %n", /* sym name, DLC, Datalen */
|
||||||
|
&sec, &usec, &interface, dir,
|
||||||
|
idstr,
|
||||||
|
&dlc, &dlen, &n) != 7) {
|
||||||
|
/* no valid CAN CC format pattern */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
read_tv.tv_sec = sec;
|
||||||
|
read_tv.tv_usec = usec;
|
||||||
|
|
||||||
|
/* check for allowed (unsigned) value ranges */
|
||||||
|
if ((dlen > CAN_MAX_DLEN) || (dlc > CAN_MAX_RAW_DLC))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (strlen(dir) != 2) /* "Rx" or "Tx" */
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (disable_dir)
|
||||||
|
dir[0] = NO_DIR;
|
||||||
|
|
||||||
|
/* check for signed integer overflow */
|
||||||
|
if (dplace == 4 && read_tv.tv_usec >= INT_MAX / 100)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* check for signed integer overflow */
|
||||||
|
if (dplace == 5 && read_tv.tv_usec >= INT_MAX / 10)
|
||||||
|
return;
|
||||||
|
|
||||||
|
get_can_id(&cf.can_id, idstr, 16);
|
||||||
|
|
||||||
|
ptr = buf + n; /* 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 FCRC to get Flags value */
|
||||||
|
if (sscanf(ptr, "%*x %x ", &flags) != 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
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;
|
||||||
|
/* sanitize payload length value */
|
||||||
|
if (dlc > CAN_MAX_DLEN)
|
||||||
|
cf.len = CAN_MAX_DLEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for extra DLC when having a Classic CAN with 8 bytes payload */
|
||||||
|
if ((cf.len == CAN_MAX_DLEN) && (dlc > CAN_MAX_DLEN) && (dlc <= CAN_MAX_RAW_DLC))
|
||||||
|
cf.len8_dlc = dlc;
|
||||||
|
|
||||||
|
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
||||||
|
prframe(outfile, &tv, interface, (cu_t *)&cf, dir[0]);
|
||||||
|
fflush(outfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void eval_canxl_fd(char* buf, struct timeval *date_tvp, char timestamps,
|
||||||
|
int dplace, int disable_dir, 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 = { 0 };
|
||||||
|
unsigned char ctmp;
|
||||||
|
unsigned int flags;
|
||||||
|
int dlc, dlen = 0;
|
||||||
|
char idstr[21];
|
||||||
|
char dir[5]; /* 'Rx'/'Tx'/'TxRq' plus terminating zero */
|
||||||
|
char *ptr;
|
||||||
|
int i;
|
||||||
|
int n = 0; /* sscanf consumed characters */
|
||||||
|
unsigned long long sec, usec;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 59.171614 CANXL 2 Rx FBFF 243215 176 432 msgCanFDTest2 \
|
||||||
|
* 9 12 e1 89 e8 c2 b9 6d 5a f1 11 22 33 44 a 12345 00001240 00000000 \
|
||||||
|
* 000000050005000e 0000000000a00010 0000000a000a001d \
|
||||||
|
* 0000000000a00002 000000100010000f 000000000a00001
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* check for valid line without symbolic name */
|
||||||
|
if (sscanf(buf,
|
||||||
|
"%llu.%llu %*s %d %4s " /* time, CANXL, channel, direction */
|
||||||
|
"%*s %*s %*s %20s " /* frame format, msg dur, bit count, ID */
|
||||||
|
"%x %d %n", /* DLC, Datalen */
|
||||||
|
&sec, &usec, &interface, dir,
|
||||||
|
idstr,
|
||||||
|
&dlc, &dlen, &n) != 7) {
|
||||||
|
/* check for valid line with a symbolic name */
|
||||||
|
if (sscanf(buf,
|
||||||
|
"%llu.%llu %*s %d %4s " /* time, CANXL, channel, direction */
|
||||||
|
"%*s %*s %*s %20s " /* frame format, msg dur, bit count, ID */
|
||||||
|
"%*s %x %d %n", /* sym name, DLC, Datalen */
|
||||||
|
&sec, &usec, &interface, dir,
|
||||||
|
idstr,
|
||||||
|
&dlc, &dlen, &n) != 7) {
|
||||||
|
/* no valid CAN CC format pattern */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
read_tv.tv_sec = sec;
|
||||||
|
read_tv.tv_usec = usec;
|
||||||
|
|
||||||
|
/* check for allowed (unsigned) value ranges */
|
||||||
|
if ((dlen > CANFD_MAX_DLEN) || (dlc > CANFD_MAX_DLC))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (strlen(dir) != 2) /* "Rx" or "Tx" */
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (disable_dir)
|
||||||
|
dir[0] = NO_DIR;
|
||||||
|
|
||||||
|
/* check for signed integer overflow */
|
||||||
|
if (dplace == 4 && read_tv.tv_usec >= INT_MAX / 100)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* check for signed integer overflow */
|
||||||
|
if (dplace == 5 && read_tv.tv_usec >= INT_MAX / 10)
|
||||||
|
return;
|
||||||
|
|
||||||
|
get_can_id(&cf.can_id, idstr, 16);
|
||||||
|
|
||||||
|
ptr = buf + n; /* 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 stuff field and FCRC to get Flags value */
|
||||||
|
if (sscanf(ptr, "%*s %*s %x ", &flags) != 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!(flags & ASC_F_FDF))
|
||||||
|
return;
|
||||||
|
|
||||||
|
cf.flags = CANFD_FDF;
|
||||||
|
|
||||||
|
if (flags & ASC_F_BRS)
|
||||||
|
cf.flags |= CANFD_BRS;
|
||||||
|
if (flags & ASC_F_ESI)
|
||||||
|
cf.flags |= CANFD_ESI;
|
||||||
|
|
||||||
|
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
||||||
|
prframe(outfile, &tv, interface, (cu_t *)&cf, dir[0]);
|
||||||
|
fflush(outfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void eval_canxl_xl(char* buf, struct timeval *date_tvp, char timestamps,
|
||||||
|
int dplace, int disable_dir, FILE *outfile)
|
||||||
|
{
|
||||||
|
int interface;
|
||||||
|
static struct timeval tv; /* current frame timestamp */
|
||||||
|
static struct timeval read_tv; /* frame timestamp from ASC file */
|
||||||
|
struct canxl_frame cf = { 0 };
|
||||||
|
unsigned char sdt, vcid, secbit, ctmp;
|
||||||
|
unsigned int af, flags;
|
||||||
|
int dlc, dlen = 0;
|
||||||
|
char idstr[21];
|
||||||
|
char dir[5]; /* 'Rx'/'Tx'/'TxRq' plus terminating zero */
|
||||||
|
char *ptr;
|
||||||
|
int i;
|
||||||
|
int n = 0; /* sscanf consumed characters */
|
||||||
|
unsigned long long sec, usec;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 59.171614 CANXL 2 Rx XLFF 984438 4656 432 msgCanXlTest1 \
|
||||||
|
* e0 0 1fe 511 1 1f96 00 00000000 e1 89 e8 c2 b9 6d 5a f1 c5 97 ( .. ) \
|
||||||
|
* ( .. ) c7 e3 4e f6 bf 12cfbd62 02503000 00000000 000000050005000e \
|
||||||
|
* 0000000000a00010 0000000a000a001d 0000000000a00002 000000100010000f \
|
||||||
|
* 000000000a00001
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* check for valid line without symbolic name */
|
||||||
|
if (sscanf(buf,
|
||||||
|
"%llu.%llu %*s %d %4s " /* time, CANXL, channel, direction */
|
||||||
|
"%*s %*s %*s %20s " /* frame format, msg dur, bit count, ID */
|
||||||
|
"%hhx %hhx %x %d " /* SDT, SEC, DLC, Datalen */
|
||||||
|
"%*s %*s %hhx %x %n", /* stuff bit count, crc, VCID, AF */
|
||||||
|
&sec, &usec, &interface, dir,
|
||||||
|
idstr,
|
||||||
|
&sdt, &secbit, &dlc, &dlen,
|
||||||
|
&vcid, &af, &n) != 11) {
|
||||||
|
/* check for valid line with a symbolic name */
|
||||||
|
if (sscanf(buf,
|
||||||
|
"%llu.%llu %*s %d %4s " /* time, CANXL, channel, direction */
|
||||||
|
"%*s %*s %*s %20s " /* frame format, msg dur, bit count, ID */
|
||||||
|
"%*s %hhx %hhx %x %d " /* sym name, SDT, SEC, DLC, Datalen */
|
||||||
|
"%*s %*s %hhx %x %n", /* stuff bit count, crc, VCID, AF */
|
||||||
|
&sec, &usec, &interface, dir,
|
||||||
|
idstr,
|
||||||
|
&sdt, &secbit, &dlc, &dlen,
|
||||||
|
&vcid, &af, &n) != 11) {
|
||||||
|
|
||||||
|
/* no valid CANXL format pattern */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
read_tv.tv_sec = sec;
|
||||||
|
read_tv.tv_usec = usec;
|
||||||
|
|
||||||
|
/* check for allowed (unsigned) value ranges */
|
||||||
|
if ((dlen > CANXL_MAX_DLEN) || (dlc > CANXL_MAX_DLC) || (secbit > 1))
|
||||||
|
return;
|
||||||
|
|
||||||
|
cf.sdt = sdt;
|
||||||
|
cf.af = af;
|
||||||
|
|
||||||
|
if (strlen(dir) != 2) /* "Rx" or "Tx" */
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (disable_dir)
|
||||||
|
dir[0] = NO_DIR;
|
||||||
|
|
||||||
|
/* check for signed integer overflow */
|
||||||
|
if (dplace == 4 && read_tv.tv_usec >= INT_MAX / 100)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* check for signed integer overflow */
|
||||||
|
if (dplace == 5 && read_tv.tv_usec >= INT_MAX / 10)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* don't trust ASCII content - sanitize data length */
|
||||||
|
if (dlen != dlc + 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
get_can_id(&cf.prio, idstr, 16);
|
||||||
|
|
||||||
|
if ((cf.prio & CANXL_PRIO_MASK) != cf.prio)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (vcid)
|
||||||
|
cf.prio |= (vcid << CANXL_VCID_OFFSET);
|
||||||
|
|
||||||
|
ptr = buf + n; /* 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 FCRC to get Flags value */
|
||||||
|
if (sscanf(ptr, "%*x %x ", &flags) != 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* mandatory for CAN XL frames */
|
||||||
|
if (!(flags & ASC_F_XLF))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* mark as CAN XL */
|
||||||
|
cf.flags = CANXL_XLF;
|
||||||
|
|
||||||
|
if (flags & ASC_F_SEC)
|
||||||
|
cf.flags |= CANXL_SEC;
|
||||||
|
|
||||||
|
if (flags & ASC_F_RES)
|
||||||
|
cf.flags |= CANXL_RRS;
|
||||||
|
|
||||||
|
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
||||||
|
prframe(outfile, &tv, interface, (cu_t *)&cf, dir[0]);
|
||||||
|
fflush(outfile);
|
||||||
|
|
||||||
|
/* No support for CAN XL ErrorFrames */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void eval_canxl(char* buf, struct timeval *date_tvp, char timestamps,
|
||||||
|
int dplace, int disable_dir, FILE *outfile)
|
||||||
|
{
|
||||||
|
int interface;
|
||||||
|
char dir[5]; /* 'Rx'/'Tx'/'TxRq' plus terminating zero */
|
||||||
|
char frfo[5]; /* frame format 'CBFF'/'CEFF'/'FBFF'/'FEFF'/'XLFF' plus terminating zero */
|
||||||
|
unsigned long long sec, usec;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The CANXL format is mainly in hex representation but <DataLength>
|
||||||
|
* and probably some content we skip anyway. Check out the new spec:
|
||||||
|
* CAN, Log & Trigger ASC Logging Format Spec V 1.4.17 of 2024-05-21
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a CAN XL ("XLFF") example for the CANXL Message Event:
|
||||||
|
*
|
||||||
|
* 59.171614 CANXL 2 Rx XLFF 984438 4656 432 msgCanXlTest1 \
|
||||||
|
* e0 0 1fe 511 1 1f96 00 00000000 e1 89 e8 c2 b9 6d 5a f1 c5 97 ( .. ) \
|
||||||
|
* ( .. ) c7 e3 4e f6 bf 12cfbd62 02503000 00000000 000000050005000e \
|
||||||
|
* 0000000000a00010 0000000a000a001d 0000000000a00002 000000100010000f \
|
||||||
|
* 000000000a00001
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* check for valid line until frame format tag */
|
||||||
|
if (sscanf(buf, "%llu.%llu %*s %d %4s %4s ",
|
||||||
|
&sec, &usec, &interface, dir, frfo) != 5)
|
||||||
|
return; /* no valid CANXL format pattern */
|
||||||
|
|
||||||
|
if (strlen(dir) != 2) /* "Rx" or "Tx" */
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (strlen(frfo) != 4) /* 'CBFF'/'CEFF'/'FBFF'/'FEFF'/'XLFF' */
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!strncmp(frfo, "XLFF", 4))
|
||||||
|
eval_canxl_xl(buf, date_tvp, timestamps, dplace, disable_dir, outfile);
|
||||||
|
else if (!strncmp(frfo, "FBFF", 4))
|
||||||
|
eval_canxl_fd(buf, date_tvp, timestamps, dplace, disable_dir, outfile);
|
||||||
|
else if (!strncmp(frfo, "FEFF", 4))
|
||||||
|
eval_canxl_fd(buf, date_tvp, timestamps, dplace, disable_dir, outfile);
|
||||||
|
else if (!strncmp(frfo, "CBFF", 4))
|
||||||
|
eval_canxl_cc(buf, date_tvp, timestamps, dplace, disable_dir, outfile);
|
||||||
|
else if (!strncmp(frfo, "CEFF", 4))
|
||||||
|
eval_canxl_cc(buf, date_tvp, timestamps, dplace, disable_dir, outfile);
|
||||||
|
}
|
||||||
|
|
||||||
static int get_date(struct timeval *tv, char *date)
|
static int get_date(struct timeval *tv, char *date)
|
||||||
{
|
{
|
||||||
struct tm tms;
|
struct tm tms;
|
||||||
|
|
@ -393,9 +790,11 @@ static int get_date(struct timeval *tv, char *date)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strptime(date, "%B %d %I:%M:%S %p %Y", &tms)) {
|
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
|
* The string might contain a milliseconds value which strptime()
|
||||||
before parsing the real year value (hack) */
|
* 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))
|
if (!strptime(date, "%B %d %I:%M:%S.%Y %p %Y", &tms))
|
||||||
return 1;
|
return 1;
|
||||||
sscanf(date, "%*s %*d %*d:%*d:%*d.%3u ", &msecs);
|
sscanf(date, "%*s %*d %*d:%*d:%*d.%3u ", &msecs);
|
||||||
|
|
@ -410,9 +809,11 @@ static int get_date(struct timeval *tv, char *date)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strptime(date, "%B %d %H:%M:%S %Y", &tms)) {
|
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
|
* The string might contain a milliseconds value which strptime()
|
||||||
before parsing the real year value (hack) */
|
* 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))
|
if (!strptime(date, "%B %d %H:%M:%S.%Y %Y", &tms))
|
||||||
return 1;
|
return 1;
|
||||||
sscanf(date, "%*s %*d %*d:%*d:%*d.%3u ", &msecs);
|
sscanf(date, "%*s %*d %*d:%*d:%*d.%3u ", &msecs);
|
||||||
|
|
@ -434,11 +835,11 @@ static int get_date(struct timeval *tv, char *date)
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char buf[BUFLEN], tmp1[BUFLEN], tmp2[BUFLEN];
|
char buf[BUFLEN], tmp1[10], tmp2[10];
|
||||||
|
|
||||||
FILE *infile = stdin;
|
FILE *infile = stdin;
|
||||||
FILE *outfile = stdout;
|
FILE *outfile = stdout;
|
||||||
static int verbose;
|
static int verbose, disable_dir;
|
||||||
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 */
|
||||||
|
|
@ -446,7 +847,7 @@ int main(int argc, char **argv)
|
||||||
int opt;
|
int opt;
|
||||||
unsigned long long sec, usec;
|
unsigned long long sec, usec;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "I:O:v?")) != -1) {
|
while ((opt = getopt(argc, argv, "I:O:dv?")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'I':
|
case 'I':
|
||||||
infile = fopen(optarg, "r");
|
infile = fopen(optarg, "r");
|
||||||
|
|
@ -464,6 +865,10 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
disable_dir = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'v':
|
case 'v':
|
||||||
verbose = 1;
|
verbose = 1;
|
||||||
break;
|
break;
|
||||||
|
|
@ -488,7 +893,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
/* check for base and timestamp entries in the header */
|
/* check for base and timestamp entries in the header */
|
||||||
if ((!base) &&
|
if ((!base) &&
|
||||||
(sscanf(buf, "base %s timestamps %s", tmp1, tmp2) == 2)) {
|
(sscanf(buf, "base %9s timestamps %9s", tmp1, tmp2) == 2)) {
|
||||||
base = tmp1[0];
|
base = tmp1[0];
|
||||||
timestamps = tmp2[0];
|
timestamps = tmp2[0];
|
||||||
if (verbose)
|
if (verbose)
|
||||||
|
|
@ -522,7 +927,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, "%llu.%s %s ", &sec, tmp2,
|
if (sscanf(buf, "%llu.%9s %9s ", &sec, tmp2,
|
||||||
tmp1) != 3)
|
tmp1) != 3)
|
||||||
continue; /* dplace remains zero until first found CAN frame */
|
continue; /* dplace remains zero until first found CAN frame */
|
||||||
|
|
||||||
|
|
@ -537,15 +942,19 @@ 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 */
|
* The representation of a valid CAN frame is known here.
|
||||||
|
* So try to get CAN frames and ErrorFrames and convert them.
|
||||||
|
*/
|
||||||
|
|
||||||
/* check classic CAN format or the CANFD tag which can take both types */
|
/* check classic CAN format or the CANFD/CANXL tag which can take different types */
|
||||||
if (sscanf(buf, "%llu.%llu %s ", &sec, &usec, tmp1) == 3){
|
if (sscanf(buf, "%llu.%llu %9s ", &sec, &usec, tmp1) == 3) {
|
||||||
if (!strncmp(tmp1, "CANFD", 5))
|
if (!strncmp(tmp1, "CANXL", 5))
|
||||||
eval_canfd(buf, &date_tv, timestamps, dplace, outfile);
|
eval_canxl(buf, &date_tv, timestamps, dplace, disable_dir, outfile);
|
||||||
|
else if (!strncmp(tmp1, "CANFD", 5))
|
||||||
|
eval_canfd(buf, &date_tv, timestamps, dplace, disable_dir, outfile);
|
||||||
else
|
else
|
||||||
eval_can(buf, &date_tv, timestamps, base, dplace, outfile);
|
eval_can(buf, &date_tv, timestamps, base, dplace, disable_dir, outfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(outfile);
|
fclose(outfile);
|
||||||
|
|
|
||||||
130
canbusload.c
130
canbusload.c
|
|
@ -45,14 +45,17 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <termios.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/param.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
@ -71,6 +74,25 @@
|
||||||
#define PERCENTRES 5 /* resolution in percent for bargraph */
|
#define PERCENTRES 5 /* resolution in percent for bargraph */
|
||||||
#define NUMBAR (100 / PERCENTRES) /* number of bargraph elements */
|
#define NUMBAR (100 / PERCENTRES) /* number of bargraph elements */
|
||||||
#define BRSTRLEN 20
|
#define BRSTRLEN 20
|
||||||
|
#define VISUAL_WINDOW 90 /* window width for visualization */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Inspired from
|
||||||
|
* https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/
|
||||||
|
* include/linux/sched/loadavg.h
|
||||||
|
*
|
||||||
|
* Following are the fixed-point math constants and the exponential-damping
|
||||||
|
* factors for:
|
||||||
|
* - 1 samples/s in 1 minute
|
||||||
|
* - 1 samples/s in 5 minutes
|
||||||
|
* - 1 samples/s in 15 minutes
|
||||||
|
* in fixed-point representation.
|
||||||
|
*/
|
||||||
|
#define FP_SHIFT 12 /* bits of precision */
|
||||||
|
#define FP_ONE (1 << FP_SHIFT) /* 1.0 fixed-point representation */
|
||||||
|
#define EXP_1 4028 /* (1 / e ^ (1 / 60)) * FP_ONE */
|
||||||
|
#define EXP_5 4082 /* (1 / e ^ (1 / 300)) * FP_ONE */
|
||||||
|
#define EXP_15 4091 /* (1 / e ^ (1 / 900)) * FP_ONE */
|
||||||
|
|
||||||
extern int optind, opterr, optopt;
|
extern int optind, opterr, optopt;
|
||||||
|
|
||||||
|
|
@ -85,19 +107,30 @@ static struct {
|
||||||
unsigned int recv_bits_total;
|
unsigned int recv_bits_total;
|
||||||
unsigned int recv_bits_payload;
|
unsigned int recv_bits_payload;
|
||||||
unsigned int recv_bits_dbitrate;
|
unsigned int recv_bits_dbitrate;
|
||||||
|
unsigned int load_min;
|
||||||
|
unsigned int load_max;
|
||||||
|
unsigned int load_1m;
|
||||||
|
unsigned int load_5m;
|
||||||
|
unsigned int load_15m;
|
||||||
|
unsigned int loads[VISUAL_WINDOW];
|
||||||
|
unsigned int index;
|
||||||
} stat[MAXDEVS + 1];
|
} stat[MAXDEVS + 1];
|
||||||
|
|
||||||
static volatile int running = 1;
|
static volatile int running = 1;
|
||||||
static volatile sig_atomic_t signal_num;
|
static volatile sig_atomic_t signal_num;
|
||||||
static int max_devname_len; /* to prevent frazzled device name output */
|
static int max_devname_len; /* to prevent frazzled device name output */
|
||||||
static int max_bitratestr_len;
|
static int max_bitratestr_len;
|
||||||
static int currmax;
|
static unsigned int currmax;
|
||||||
static unsigned char redraw;
|
static unsigned char redraw;
|
||||||
static unsigned char timestamp;
|
static unsigned char timestamp;
|
||||||
static unsigned char color;
|
static unsigned char color;
|
||||||
static unsigned char bargraph;
|
static unsigned char bargraph;
|
||||||
|
static bool statistic;
|
||||||
|
static bool reset;
|
||||||
|
static bool visualize;
|
||||||
static enum cfl_mode mode = CFL_WORSTCASE;
|
static enum cfl_mode mode = CFL_WORSTCASE;
|
||||||
static char *prg;
|
static char *prg;
|
||||||
|
static struct termios old;
|
||||||
|
|
||||||
static void print_usage(char *prg)
|
static void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
|
|
@ -111,6 +144,8 @@ static void print_usage(char *prg)
|
||||||
fprintf(stderr, " -r (redraw the terminal - similar to top)\n");
|
fprintf(stderr, " -r (redraw the terminal - similar to top)\n");
|
||||||
fprintf(stderr, " -i (ignore bitstuffing in bandwidth calculation)\n");
|
fprintf(stderr, " -i (ignore bitstuffing in bandwidth calculation)\n");
|
||||||
fprintf(stderr, " -e (exact calculation of stuffed bits)\n");
|
fprintf(stderr, " -e (exact calculation of stuffed bits)\n");
|
||||||
|
fprintf(stderr, " -s (show statistics, press 'r' to reset)\n");
|
||||||
|
fprintf(stderr, " -v (show busload visualization)\n");
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "Up to %d CAN interfaces with mandatory bitrate can be specified on the \n", MAXDEVS);
|
fprintf(stderr, "Up to %d CAN interfaces with mandatory bitrate can be specified on the \n", MAXDEVS);
|
||||||
fprintf(stderr, "commandline in the form: <ifname>@<bitrate>[,<dbitrate>]\n");
|
fprintf(stderr, "commandline in the form: <ifname>@<bitrate>[,<dbitrate>]\n");
|
||||||
|
|
@ -161,9 +196,19 @@ static void create_bitrate_string(int stat_idx, int *max_bitratestr_len)
|
||||||
*max_bitratestr_len = ptr;
|
*max_bitratestr_len = ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int calc_load(unsigned int load_fp,
|
||||||
|
unsigned int exp_fp,
|
||||||
|
unsigned int sample)
|
||||||
|
{
|
||||||
|
unsigned int sample_fp = sample << FP_SHIFT;
|
||||||
|
unsigned int damped_sum = (load_fp * exp_fp) +
|
||||||
|
(sample_fp * (FP_ONE - exp_fp));
|
||||||
|
return damped_sum >> FP_SHIFT;
|
||||||
|
}
|
||||||
|
|
||||||
static void printstats(int signo)
|
static void printstats(int signo)
|
||||||
{
|
{
|
||||||
int i, j, percent;
|
unsigned int i, j, k, percent, index;
|
||||||
|
|
||||||
if (redraw)
|
if (redraw)
|
||||||
printf("%s", CSR_HOME);
|
printf("%s", CSR_HOME);
|
||||||
|
|
@ -234,6 +279,30 @@ static void printstats(int signo)
|
||||||
stat[i].recv_bits_dbitrate,
|
stat[i].recv_bits_dbitrate,
|
||||||
percent);
|
percent);
|
||||||
|
|
||||||
|
if (statistic) {
|
||||||
|
if (reset) {
|
||||||
|
stat[i].load_min = UINT_MAX;
|
||||||
|
stat[i].load_max = 0;
|
||||||
|
stat[i].load_1m = 0;
|
||||||
|
stat[i].load_5m = 0;
|
||||||
|
stat[i].load_15m = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
stat[i].load_min = MIN(stat[i].load_min, percent);
|
||||||
|
stat[i].load_max = MAX(stat[i].load_max, percent);
|
||||||
|
|
||||||
|
stat[i].load_1m = calc_load(stat[i].load_1m, EXP_1, percent);
|
||||||
|
stat[i].load_5m = calc_load(stat[i].load_5m, EXP_5, percent);
|
||||||
|
stat[i].load_15m = calc_load(stat[i].load_15m, EXP_15, percent);
|
||||||
|
|
||||||
|
printf(" min:%3d%%, max:%3d%%, load:%3d%% %3d%% %3d%%",
|
||||||
|
stat[i].load_min,
|
||||||
|
stat[i].load_max,
|
||||||
|
(stat[i].load_1m + (FP_ONE >> 1)) >> FP_SHIFT,
|
||||||
|
(stat[i].load_5m + (FP_ONE >> 1)) >> FP_SHIFT,
|
||||||
|
(stat[i].load_15m + (FP_ONE >> 1)) >> FP_SHIFT);
|
||||||
|
}
|
||||||
|
|
||||||
if (bargraph) {
|
if (bargraph) {
|
||||||
|
|
||||||
printf(" |");
|
printf(" |");
|
||||||
|
|
@ -251,6 +320,28 @@ static void printstats(int signo)
|
||||||
printf("|");
|
printf("|");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (visualize) {
|
||||||
|
stat[i].loads[stat[i].index] = percent;
|
||||||
|
stat[i].index = (stat[i].index + 1) % VISUAL_WINDOW;
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
for (j = 0; j < NUMBAR; j++) {
|
||||||
|
printf("%3d%%|", (NUMBAR - j) * PERCENTRES);
|
||||||
|
index = stat[i].index;
|
||||||
|
for (k = 0; k < VISUAL_WINDOW; k++) {
|
||||||
|
percent = stat[i].loads[index];
|
||||||
|
|
||||||
|
if ((percent / PERCENTRES) >= (NUMBAR - j))
|
||||||
|
printf("X");
|
||||||
|
else
|
||||||
|
printf(".");
|
||||||
|
|
||||||
|
index = (index + 1) % VISUAL_WINDOW;
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (color)
|
if (color)
|
||||||
printf("%s", ATTRESET);
|
printf("%s", ATTRESET);
|
||||||
|
|
||||||
|
|
@ -264,6 +355,8 @@ static void printstats(int signo)
|
||||||
stat[i].recv_direction = '.';
|
stat[i].recv_direction = '.';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reset = false;
|
||||||
|
|
||||||
if (!redraw)
|
if (!redraw)
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
|
|
@ -272,6 +365,11 @@ static void printstats(int signo)
|
||||||
alarm(1);
|
alarm(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cleanup()
|
||||||
|
{
|
||||||
|
tcsetattr(STDIN_FILENO, TCSANOW, &old);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
fd_set rdfs;
|
fd_set rdfs;
|
||||||
|
|
@ -282,12 +380,20 @@ int main(int argc, char **argv)
|
||||||
struct canfd_frame frame;
|
struct canfd_frame frame;
|
||||||
struct iovec iov;
|
struct iovec iov;
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
int nbytes, i;
|
unsigned int i;
|
||||||
|
int nbytes;
|
||||||
|
|
||||||
int have_anydev = 0;
|
int have_anydev = 0;
|
||||||
unsigned int anydev_bitrate = 0;
|
unsigned int anydev_bitrate = 0;
|
||||||
unsigned int anydev_dbitrate = 0;
|
unsigned int anydev_dbitrate = 0;
|
||||||
char anydev_bitratestr[BRSTRLEN]; /* 100000/2000000 => 100k/2M */
|
char anydev_bitratestr[BRSTRLEN]; /* 100000/2000000 => 100k/2M */
|
||||||
|
struct termios temp;
|
||||||
|
|
||||||
|
tcgetattr(STDIN_FILENO, &old);
|
||||||
|
atexit(cleanup);
|
||||||
|
temp = old;
|
||||||
|
temp.c_lflag &= ~(ICANON | ECHO);
|
||||||
|
tcsetattr(STDIN_FILENO, TCSANOW, &temp);
|
||||||
|
|
||||||
signal(SIGTERM, sigterm);
|
signal(SIGTERM, sigterm);
|
||||||
signal(SIGHUP, sigterm);
|
signal(SIGHUP, sigterm);
|
||||||
|
|
@ -297,7 +403,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
prg = basename(argv[0]);
|
prg = basename(argv[0]);
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "rtbcieh?")) != -1) {
|
while ((opt = getopt(argc, argv, "rtbciesvh?")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'r':
|
case 'r':
|
||||||
redraw = 1;
|
redraw = 1;
|
||||||
|
|
@ -323,6 +429,15 @@ int main(int argc, char **argv)
|
||||||
mode = CFL_EXACT;
|
mode = CFL_EXACT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
statistic = true;
|
||||||
|
reset = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'v':
|
||||||
|
visualize = true;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
print_usage(prg);
|
print_usage(prg);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
@ -449,12 +564,19 @@ int main(int argc, char **argv)
|
||||||
while (running) {
|
while (running) {
|
||||||
FD_ZERO(&rdfs);
|
FD_ZERO(&rdfs);
|
||||||
FD_SET(s, &rdfs);
|
FD_SET(s, &rdfs);
|
||||||
|
FD_SET(STDIN_FILENO, &rdfs);
|
||||||
|
|
||||||
if (select(s + 1, &rdfs, NULL, NULL, NULL) < 0) {
|
if (select(s + 1, &rdfs, NULL, NULL, NULL) < 0) {
|
||||||
//perror("pselect");
|
//perror("pselect");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FD_ISSET(STDIN_FILENO, &rdfs)) {
|
||||||
|
if (getchar() == 'r') {
|
||||||
|
reset = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* these settings may be modified by recvmsg() */
|
/* these settings may be modified by recvmsg() */
|
||||||
iov.iov_len = sizeof(frame);
|
iov.iov_len = sizeof(frame);
|
||||||
msg.msg_namelen = sizeof(addr);
|
msg.msg_namelen = sizeof(addr);
|
||||||
|
|
|
||||||
22
cangen.c
22
cangen.c
|
|
@ -189,6 +189,7 @@ static void print_usage(char *prg)
|
||||||
fprintf(stderr, " -A <mode> (CAN XL AF generation mode - see below, no e/o mode)\n");
|
fprintf(stderr, " -A <mode> (CAN XL AF generation mode - see below, no e/o mode)\n");
|
||||||
fprintf(stderr, " -V <mode> (CAN XL VCID generation mode - see below, no e/o mode)\n");
|
fprintf(stderr, " -V <mode> (CAN XL VCID generation mode - see below, no e/o mode)\n");
|
||||||
fprintf(stderr, " -p <timeout> (poll on -ENOBUFS to write frames with <timeout> ms)\n");
|
fprintf(stderr, " -p <timeout> (poll on -ENOBUFS to write frames with <timeout> ms)\n");
|
||||||
|
fprintf(stderr, " -P <priority> (set socket priority using SO_PRIORITY)\n");
|
||||||
fprintf(stderr, " -n <count> (terminate after <count> CAN frames - default infinite)\n");
|
fprintf(stderr, " -n <count> (terminate after <count> CAN frames - default infinite)\n");
|
||||||
fprintf(stderr, " -i (ignore -ENOBUFS return values on write() syscalls)\n");
|
fprintf(stderr, " -i (ignore -ENOBUFS return values on write() syscalls)\n");
|
||||||
fprintf(stderr, " -x (disable local loopback of generated CAN frames)\n");
|
fprintf(stderr, " -x (disable local loopback of generated CAN frames)\n");
|
||||||
|
|
@ -479,6 +480,7 @@ int main(int argc, char **argv)
|
||||||
uint64_t incdata = 0;
|
uint64_t incdata = 0;
|
||||||
__u8 *data; /* base pointer for CC/FD or XL data */
|
__u8 *data; /* base pointer for CC/FD or XL data */
|
||||||
int incdlc = 0;
|
int incdlc = 0;
|
||||||
|
int priority = -1;
|
||||||
unsigned long rnd;
|
unsigned long rnd;
|
||||||
unsigned char fixdata[CANFD_MAX_DLEN];
|
unsigned char fixdata[CANFD_MAX_DLEN];
|
||||||
unsigned char rand_position[CANFD_MAX_DLEN] = { 0 };
|
unsigned char rand_position[CANFD_MAX_DLEN] = { 0 };
|
||||||
|
|
@ -512,7 +514,7 @@ int main(int argc, char **argv)
|
||||||
{ 0, 0, 0, 0 },
|
{ 0, 0, 0, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
while ((opt = getopt_long(argc, argv, "g:atefbEXR8mI:L:D:F:S:A:V:p:n:ixc:vh?", long_options, NULL)) != -1) {
|
while ((opt = getopt_long(argc, argv, "g:atefbEXR8mI:L:D:F:S:A:V:p:P:n:ixc:vh?", long_options, NULL)) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'g':
|
case 'g':
|
||||||
gap = strtod(optarg, NULL);
|
gap = strtod(optarg, NULL);
|
||||||
|
|
@ -682,6 +684,14 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'P':
|
||||||
|
priority = atoi(optarg);
|
||||||
|
if (priority < 0) {
|
||||||
|
printf("socket priority has to be >= 0\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
ignore_enobufs = true;
|
ignore_enobufs = true;
|
||||||
break;
|
break;
|
||||||
|
|
@ -750,6 +760,16 @@ int main(int argc, char **argv)
|
||||||
*/
|
*/
|
||||||
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
|
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* user can use tc to configure the queuing discipline (e.g. mqprio),
|
||||||
|
* together with SO_PRIORITY option to specify the message send from
|
||||||
|
* this socket should go to which queue.
|
||||||
|
*/
|
||||||
|
if (priority >= 0 &&
|
||||||
|
setsockopt(s, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority))) {
|
||||||
|
printf("error setting SO_PRIORITY\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (loopback_disable) {
|
if (loopback_disable) {
|
||||||
const int loopback = 0;
|
const int loopback = 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,7 @@ struct canfd_frame {
|
||||||
/*
|
/*
|
||||||
* defined bits for canxl_frame.flags
|
* defined bits for canxl_frame.flags
|
||||||
*
|
*
|
||||||
* The canxl_frame.flags element contains two bits CANXL_XLF and CANXL_SEC
|
* The canxl_frame.flags element contains three bits CANXL_[XLF|SEC|RRS]
|
||||||
* and shares the relative position of the struct can[fd]_frame.len element.
|
* and shares the relative position of the struct can[fd]_frame.len element.
|
||||||
* The CANXL_XLF bit ALWAYS needs to be set to indicate a valid CAN XL frame.
|
* The CANXL_XLF bit ALWAYS needs to be set to indicate a valid CAN XL frame.
|
||||||
* As a side effect setting this bit intentionally breaks the length checks
|
* As a side effect setting this bit intentionally breaks the length checks
|
||||||
|
|
@ -192,6 +192,7 @@ struct canfd_frame {
|
||||||
*/
|
*/
|
||||||
#define CANXL_XLF 0x80 /* mandatory CAN XL frame flag (must always be set!) */
|
#define CANXL_XLF 0x80 /* mandatory CAN XL frame flag (must always be set!) */
|
||||||
#define CANXL_SEC 0x01 /* Simple Extended Content (security/segmentation) */
|
#define CANXL_SEC 0x01 /* Simple Extended Content (security/segmentation) */
|
||||||
|
#define CANXL_RRS 0x02 /* Remote Request Substitution */
|
||||||
|
|
||||||
/* the 8-bit VCID is optionally placed in the canxl_frame.prio element */
|
/* the 8-bit VCID is optionally placed in the canxl_frame.prio element */
|
||||||
#define CANXL_VCID_OFFSET 16 /* bit offset of VCID in prio element */
|
#define CANXL_VCID_OFFSET 16 /* bit offset of VCID in prio element */
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
25
libj1939.c
25
libj1939.c
|
|
@ -253,6 +253,31 @@ int libj1939_bind_socket(int sock, struct sockaddr_can *addr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* libj1939_connect_socket - Connects a socket to a CAN address.
|
||||||
|
* @sock: The socket file descriptor.
|
||||||
|
* @addr: The CAN address to connect to.
|
||||||
|
*
|
||||||
|
* This function attempts to establish a connection between the given socket
|
||||||
|
* and the specified CAN address. If the connection fails, it logs an error
|
||||||
|
* message with the error code and a description of the error.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, or a negative error code on failure.
|
||||||
|
*/
|
||||||
|
int libj1939_connect_socket(int sock, struct sockaddr_can *addr)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = connect(sock, (void *)addr, sizeof(*addr));
|
||||||
|
if (ret < 0) {
|
||||||
|
ret = -errno;
|
||||||
|
pr_err("failed to connect socket: %d (%s)", ret, strerror(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* libj1939_socket_prio - Set the priority of a J1939 socket
|
* libj1939_socket_prio - Set the priority of a J1939 socket
|
||||||
* @sock: The file descriptor of the socket
|
* @sock: The file descriptor of the socket
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
#include <linux/can/j1939.h>
|
#include <linux/can/j1939.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <time.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
#ifndef J1939_LIB_H
|
#ifndef J1939_LIB_H
|
||||||
|
|
@ -42,6 +43,7 @@ void libj1939_init_sockaddr_can(struct sockaddr_can *sac, uint32_t pgn);
|
||||||
|
|
||||||
int libj1939_open_socket(void);
|
int libj1939_open_socket(void);
|
||||||
int libj1939_bind_socket(int sock, struct sockaddr_can *addr);
|
int libj1939_bind_socket(int sock, struct sockaddr_can *addr);
|
||||||
|
int libj1939_connect_socket(int sock, struct sockaddr_can *addr);
|
||||||
int libj1939_socket_prio(int sock, int prio);
|
int libj1939_socket_prio(int sock, int prio);
|
||||||
int libj1939_set_broadcast(int sock);
|
int libj1939_set_broadcast(int sock);
|
||||||
int libj1939_add_socket_to_epoll(int epoll_fd, int sock, uint32_t events);
|
int libj1939_add_socket_to_epoll(int epoll_fd, int sock, uint32_t events);
|
||||||
|
|
|
||||||
172
log2asc.c
172
log2asc.c
|
|
@ -54,6 +54,15 @@
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
#define ASC_F_XLF 0x00400000
|
||||||
|
#define ASC_F_RES 0x00800000
|
||||||
|
#define ASC_F_SEC 0x01000000
|
||||||
|
|
||||||
extern int optind, opterr, optopt;
|
extern int optind, opterr, optopt;
|
||||||
|
|
||||||
static void print_usage(char *prg)
|
static void print_usage(char *prg)
|
||||||
|
|
@ -65,18 +74,17 @@ static void print_usage(char *prg)
|
||||||
fprintf(stderr, " -O <outfile> (default stdout)\n");
|
fprintf(stderr, " -O <outfile> (default stdout)\n");
|
||||||
fprintf(stderr, " -4 (reduce decimal place to 4 digits)\n");
|
fprintf(stderr, " -4 (reduce decimal place to 4 digits)\n");
|
||||||
fprintf(stderr, " -n (set newline to cr/lf - default lf)\n");
|
fprintf(stderr, " -n (set newline to cr/lf - default lf)\n");
|
||||||
fprintf(stderr, " -f (use CANFD format also for Classic CAN)\n");
|
fprintf(stderr, " -f (use CANFD format also for CAN CC)\n");
|
||||||
|
fprintf(stderr, " -x (use CANXL format also for CAN CC/FD)\n");
|
||||||
fprintf(stderr, " -r (suppress dlc for RTR frames - pre v8.5 tools)\n");
|
fprintf(stderr, " -r (suppress dlc for RTR frames - pre v8.5 tools)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void can_asc(struct canfd_frame *cfd, int devno, int nortrdlc,
|
static void can_asc(struct can_frame *cf, int devno, int nortrdlc,
|
||||||
char *extra_info, FILE *outfile)
|
char *extra_info, FILE *outfile)
|
||||||
{
|
{
|
||||||
int i;
|
unsigned int i, dlc;
|
||||||
char id[10];
|
char id[10];
|
||||||
char *dir = "Rx";
|
char *dir = "Rx";
|
||||||
int dlc;
|
|
||||||
struct can_frame *cf = (struct can_frame *)cfd; /* for len8_dlc */
|
|
||||||
|
|
||||||
fprintf(outfile, "%-2d ", devno); /* channel number left aligned */
|
fprintf(outfile, "%-2d ", devno); /* channel number left aligned */
|
||||||
|
|
||||||
|
|
@ -93,7 +101,7 @@ static void can_asc(struct canfd_frame *cfd, int devno, int nortrdlc,
|
||||||
dir = "Tx";
|
dir = "Tx";
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(outfile, "%-15s %s ", id, dir);
|
fprintf(outfile, "%-15s %-4s ", id, dir);
|
||||||
|
|
||||||
if (cf->len == CAN_MAX_DLC &&
|
if (cf->len == CAN_MAX_DLC &&
|
||||||
cf->len8_dlc > CAN_MAX_DLC &&
|
cf->len8_dlc > CAN_MAX_DLC &&
|
||||||
|
|
@ -120,19 +128,13 @@ static void can_asc(struct canfd_frame *cfd, int devno, int nortrdlc,
|
||||||
static void canfd_asc(struct canfd_frame *cf, int devno, int mtu,
|
static void canfd_asc(struct canfd_frame *cf, int devno, int mtu,
|
||||||
char *extra_info, FILE *outfile)
|
char *extra_info, FILE *outfile)
|
||||||
{
|
{
|
||||||
int i;
|
unsigned int i;
|
||||||
char id[10];
|
char id[10];
|
||||||
char *dir = "Rx";
|
char *dir = "Rx";
|
||||||
unsigned int flags = 0;
|
unsigned int flags = 0;
|
||||||
unsigned int dlen = cf->len;
|
unsigned int dlen = cf->len;
|
||||||
unsigned int dlc = can_fd_len2dlc(dlen);
|
unsigned int dlc = can_fd_len2dlc(dlen);
|
||||||
|
|
||||||
/* 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
|
|
||||||
|
|
||||||
/* check for extra info */
|
/* check for extra info */
|
||||||
if (strlen(extra_info) > 0) {
|
if (strlen(extra_info) > 0) {
|
||||||
/* only the first char is defined so far */
|
/* only the first char is defined so far */
|
||||||
|
|
@ -140,7 +142,7 @@ static void canfd_asc(struct canfd_frame *cf, int devno, int mtu,
|
||||||
dir = "Tx";
|
dir = "Tx";
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(outfile, "CANFD %3d %s ", devno, dir); /* 3 column channel number right aligned */
|
fprintf(outfile, "CANFD %3d %-4s ", devno, dir); /* 3 column channel number right aligned */
|
||||||
|
|
||||||
sprintf(id, "%X%c", cf->can_id & CAN_EFF_MASK,
|
sprintf(id, "%X%c", cf->can_id & CAN_EFF_MASK,
|
||||||
(cf->can_id & CAN_EFF_FLAG)?'x':' ');
|
(cf->can_id & CAN_EFF_FLAG)?'x':' ');
|
||||||
|
|
@ -174,13 +176,124 @@ static void canfd_asc(struct canfd_frame *cf, int devno, int mtu,
|
||||||
|
|
||||||
fprintf(outfile, "%2d", dlen);
|
fprintf(outfile, "%2d", dlen);
|
||||||
|
|
||||||
for (i = 0; i < (int)dlen; i++) {
|
for (i = 0; i < dlen; i++) {
|
||||||
fprintf(outfile, " %02X", cf->data[i]);
|
fprintf(outfile, " %02X", cf->data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(outfile, " %8d %4d %8X 0 0 0 0 0", 130000, 130, flags);
|
fprintf(outfile, " %8d %4d %8X 0 0 0 0 0", 130000, 130, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void canxl_asc(cu_t *cu, int devno, int mtu,
|
||||||
|
char *extra_info, FILE *outfile)
|
||||||
|
{
|
||||||
|
char id[10];
|
||||||
|
char *dir = "Rx";
|
||||||
|
char *frametype;
|
||||||
|
unsigned char *dataptr;
|
||||||
|
unsigned int i, dlen, dlc, flags = 0;
|
||||||
|
|
||||||
|
/* check for extra info */
|
||||||
|
if (strlen(extra_info) > 0) {
|
||||||
|
/* only the first char is defined so far */
|
||||||
|
if (extra_info[0] == 'T')
|
||||||
|
dir = "Tx";
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (mtu) {
|
||||||
|
case CANXL_MTU:
|
||||||
|
sprintf(id, "%X", cu->xl.prio & CANXL_PRIO_MASK);
|
||||||
|
frametype = "XLFF";
|
||||||
|
|
||||||
|
dataptr = &cu->xl.data[0];
|
||||||
|
dlen = cu->xl.len;
|
||||||
|
dlc = dlen - 1;
|
||||||
|
flags = (ASC_F_XLF | ASC_F_FDF | ASC_F_BRS);
|
||||||
|
|
||||||
|
if (cu->xl.flags & CANXL_SEC)
|
||||||
|
flags |= ASC_F_SEC;
|
||||||
|
if (cu->xl.flags & CANXL_RRS)
|
||||||
|
flags |= ASC_F_RES;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CANFD_MTU:
|
||||||
|
if (cu->fd.can_id & CAN_EFF_FLAG) {
|
||||||
|
sprintf(id, "%Xx", cu->fd.can_id & CAN_EFF_MASK);
|
||||||
|
frametype = "FEFF";
|
||||||
|
} else {
|
||||||
|
sprintf(id, "%X", cu->fd.can_id & CAN_SFF_MASK);
|
||||||
|
frametype = "FBFF";
|
||||||
|
}
|
||||||
|
|
||||||
|
dataptr = &cu->fd.data[0];
|
||||||
|
dlen = cu->fd.len;
|
||||||
|
dlc = can_fd_len2dlc(dlen);
|
||||||
|
flags = ASC_F_FDF;
|
||||||
|
if (cu->fd.flags & CANFD_BRS)
|
||||||
|
flags |= ASC_F_BRS;
|
||||||
|
if (cu->fd.flags & CANFD_ESI)
|
||||||
|
flags |= ASC_F_ESI;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CAN_MTU:
|
||||||
|
if (cu->cc.can_id & CAN_EFF_FLAG) {
|
||||||
|
sprintf(id, "%Xx", cu->cc.can_id & CAN_EFF_MASK);
|
||||||
|
frametype = "CEFF";
|
||||||
|
} else {
|
||||||
|
sprintf(id, "%X", cu->cc.can_id & CAN_SFF_MASK);
|
||||||
|
frametype = "CBFF";
|
||||||
|
}
|
||||||
|
|
||||||
|
dataptr = &cu->cc.data[0];
|
||||||
|
dlen = cu->cc.len;
|
||||||
|
dlc = dlen ;
|
||||||
|
|
||||||
|
/* check for extra DLC when having a Classic CAN with 8 bytes payload */
|
||||||
|
if ((dlen == CAN_MAX_DLEN) && (cu->cc.len8_dlc > CAN_MAX_DLEN) &&
|
||||||
|
(cu->cc.len8_dlc <= CAN_MAX_RAW_DLC))
|
||||||
|
dlc = cu->cc.len8_dlc;
|
||||||
|
|
||||||
|
if (cu->cc.can_id & CAN_RTR_FLAG) {
|
||||||
|
/* no data length but dlc for RTR frames */
|
||||||
|
dlen = 0;
|
||||||
|
flags = ASC_F_RTR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(outfile, "CANXL %3d %-4s ", devno, dir); /* 3 column channel number and direction */
|
||||||
|
|
||||||
|
fprintf(outfile, "%s 984438 4656 ", frametype); /* frame type / msg duration / bit count */
|
||||||
|
|
||||||
|
fprintf(outfile, "%9s ", id); /* ID / symbolic name (empty) */
|
||||||
|
|
||||||
|
if (mtu == CANXL_MTU) /* SDT, SEC bit for CAN XL only */
|
||||||
|
fprintf(outfile, "%02x %d ", cu->xl.sdt, (cu->xl.flags & CANXL_SEC)?1:0);
|
||||||
|
|
||||||
|
fprintf(outfile, "%x %d", dlc, dlen); /* DLC and data length */
|
||||||
|
|
||||||
|
if (mtu == CANXL_MTU) /* SBC / PCRC / VCID / AF */
|
||||||
|
fprintf(outfile, " 1 1f96 %02x %08x",
|
||||||
|
(unsigned char)((cu->xl.prio >> CANXL_VCID_OFFSET) & CANXL_VCID_VAL_MASK),
|
||||||
|
cu->xl.af);
|
||||||
|
|
||||||
|
for (i = 0; i < dlen; i++) {
|
||||||
|
fprintf(outfile, " %02x", dataptr[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mtu == CANFD_MTU) /* stuff field */
|
||||||
|
fprintf(outfile, " 8");
|
||||||
|
|
||||||
|
fprintf(outfile, " 123123 %08x %08x", flags, 0); /* fcsc, msg flags, msg flags ext */
|
||||||
|
|
||||||
|
fprintf(outfile, /* bitrate settings for CC/FD/XL */
|
||||||
|
" 000000050005000e 0000000000a00010"
|
||||||
|
" 0000000a000a001d 0000000000a00002"
|
||||||
|
" 000000100010000f 0000000000a00001");
|
||||||
|
}
|
||||||
|
|
||||||
#define DEVSZ 22
|
#define DEVSZ 22
|
||||||
#define EXTRASZ 20
|
#define EXTRASZ 20
|
||||||
#define TIMESZ sizeof("(1345212884.318850) ")
|
#define TIMESZ sizeof("(1345212884.318850) ")
|
||||||
|
|
@ -205,11 +318,11 @@ int main(int argc, char **argv)
|
||||||
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, fdfmt, nortrdlc, d4, opt, mtu;
|
static int maxdev, devno, i, crlf, fdfmt, xlfmt, nortrdlc, d4, opt, mtu;
|
||||||
int print_banner = 1;
|
int print_banner = 1;
|
||||||
unsigned long long sec, usec;
|
unsigned long long sec, usec;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "I:O:4nfr?")) != -1) {
|
while ((opt = getopt(argc, argv, "I:O:4nfxr?")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'I':
|
case 'I':
|
||||||
infile = fopen(optarg, "r");
|
infile = fopen(optarg, "r");
|
||||||
|
|
@ -235,6 +348,10 @@ int main(int argc, char **argv)
|
||||||
fdfmt = 1;
|
fdfmt = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'x':
|
||||||
|
xlfmt = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
nortrdlc = 1;
|
nortrdlc = 1;
|
||||||
break;
|
break;
|
||||||
|
|
@ -300,6 +417,9 @@ int main(int argc, char **argv)
|
||||||
(crlf)?"\r\n":"\n");
|
(crlf)?"\r\n":"\n");
|
||||||
fprintf(outfile, "no internal events logged%s",
|
fprintf(outfile, "no internal events logged%s",
|
||||||
(crlf)?"\r\n":"\n");
|
(crlf)?"\r\n":"\n");
|
||||||
|
fprintf(outfile, "// version 18.2.0%s", (crlf)?"\r\n":"\n");
|
||||||
|
fprintf(outfile, "// Measurement UUID: cc9c7b54-68ae-"
|
||||||
|
"46d2-a43a-6aa87df7dd74%s", (crlf)?"\r\n":"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0, devno = 0; i < maxdev; i++) {
|
for (i = 0, devno = 0; i < maxdev; i++) {
|
||||||
|
|
@ -313,14 +433,8 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
mtu = parse_canframe(afrbuf, &cu);
|
mtu = parse_canframe(afrbuf, &cu);
|
||||||
|
|
||||||
/* convert only CAN CC and CAN FD frames */
|
/* no error message frames in non CAN CC frames */
|
||||||
if ((mtu != CAN_MTU) && (mtu != CANFD_MTU)) {
|
if ((mtu != CAN_MTU) && (cu.cc.can_id & CAN_ERR_FLAG))
|
||||||
printf("no valid CAN CC/FD frame\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we don't support error message frames in CAN FD */
|
|
||||||
if ((mtu == CANFD_MTU) && (cu.cc.can_id & CAN_ERR_FLAG))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
tv.tv_sec = tv.tv_sec - start_tv.tv_sec;
|
tv.tv_sec = tv.tv_sec - start_tv.tv_sec;
|
||||||
|
|
@ -335,10 +449,12 @@ int main(int argc, char **argv)
|
||||||
else
|
else
|
||||||
fprintf(outfile, "%4llu.%06llu ", (unsigned long long)tv.tv_sec, (unsigned long long)tv.tv_usec);
|
fprintf(outfile, "%4llu.%06llu ", (unsigned long long)tv.tv_sec, (unsigned long long)tv.tv_usec);
|
||||||
|
|
||||||
if ((mtu == CAN_MTU) && (fdfmt == 0))
|
if ((mtu == CAN_MTU) && (fdfmt == 0) && (xlfmt == 0))
|
||||||
can_asc(&cu.fd, devno, nortrdlc, extra_info, outfile);
|
can_asc(&cu.cc, devno, nortrdlc, extra_info, outfile);
|
||||||
else
|
else if ((mtu != CANXL_MTU) && (xlfmt == 0))
|
||||||
canfd_asc(&cu.fd, devno, mtu, extra_info, outfile);
|
canfd_asc(&cu.fd, devno, mtu, extra_info, outfile);
|
||||||
|
else
|
||||||
|
canxl_asc(&cu, devno, mtu, extra_info, outfile);
|
||||||
|
|
||||||
if (crlf)
|
if (crlf)
|
||||||
fprintf(outfile, "\r");
|
fprintf(outfile, "\r");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue