4 Commits
Author SHA1 Message Date
Oleksij RempelandGitHub aca13487c6 Merge 2638b3965c into 2b8c7c5f4b 2025-02-16 22:12:06 +00:00
Oleksij Rempel 2638b3965c j1939-vehicle-position-srv: Introduce J1939 and NMEA 2000 Vehicle Position Server
This patch adds `j1939-vehicle-position-srv`, a server for sending
vehicle position data over CAN using J1939 or NMEA 2000 protocols. It
retrieves GPS data from gpsd or simulates data if gpsd is unavailable.
By default, it operates in J1939 profile but can switch to NMEA 2000
with the `-p nmea2000` option.

Usage Examples:
1. With gpsd:
   j1939acd -r 64-95 -c /tmp/1122334455667789.jacd 1122334455667789 vcan0 &
   j1939-vehicle-position-srv -i vcan0 -n 0x1122334455667789

2. In simulation mode without gpsd:
   j1939-vehicle-position-srv -i vcan0 -s -p nmea2000

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
2024-12-29 12:03:18 +01:00
Marc Kleine-BuddeandOleksij Rempel 93e7b02236 github-actions: install libgps-dev 2024-12-28 11:26:20 +01:00
Oleksij Rempel 590b8df5a8 libj1939: Add function to connect a socket
Introduce `libj1939_connect_socket` function to handle socket
connections.

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
2024-12-28 11:08:09 +01:00
40 changed files with 1027 additions and 1875 deletions
+15 -68
View File
@@ -30,43 +30,8 @@ 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
- name: Update APT Sources List (Ubuntu Only)
if:
startsWith(matrix.release, 'ubuntu:') && matrix.release != 'ubuntu:20.04'
run: |
podman exec -i -u root stable apt update
podman exec -e DEBIAN_FRONTEND='noninteractive' -i -u root stable apt install -o APT::Install-Suggests=false -qy \
lsb-release
podman exec -i -u root stable \
test -e /etc/apt/sources.list &&
podman exec -i -u root stable \
sed -i -e 's|\(http.*:\)|[arch=amd64] \1|g' /etc/apt/sources.list
podman exec -i -u root stable \
test -e /etc/apt/sources.list.d/ubuntu.sources &&
podman exec -i -u root stable \
sed -i -e '/^Components:/a Architectures: amd64' /etc/apt/sources.list.d/ubuntu.sources
echo "deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports/ $(podman exec -i stable lsb_release -cs) main restricted universe multiverse" | \
podman exec -i -u root stable tee -a /etc/apt/sources.list.d/cross.list
echo "deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports/ $(podman exec -i stable lsb_release -cs)-updates main restricted universe multiverse" | \
podman exec -i -u root stable tee -a /etc/apt/sources.list.d/cross.list
echo "deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports/ $(podman exec -i stable lsb_release -cs)-backports main restricted universe multiverse" | \
podman exec -i -u root stable tee -a /etc/apt/sources.list.d/cross.list
- name: Add Architecture
if:
matrix.release != 'ubuntu:20.04'
run: |
podman exec -i -u root stable dpkg --add-architecture arm64 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 dpkg --add-architecture armhf
- name: Install Development Packages
env:
release: ${{ matrix.release == 'debian:experimental' && '-t experimental' || '' }}
run: |
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 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} \
@@ -75,82 +40,64 @@ jobs:
gcc \ gcc \
gcc-aarch64-linux-gnu \ gcc-aarch64-linux-gnu \
gcc-arm-linux-gnueabihf \ gcc-arm-linux-gnueabihf \
gcc-mips-linux-gnu \
libgps-dev \ libgps-dev \
make
- name: Install Cross Libs
env:
release: ${{ matrix.release == 'debian:experimental' && '-t experimental' || '' }}
if:
matrix.release != 'ubuntu:20.04'
run: |
podman exec -e DEBIAN_FRONTEND='noninteractive' -i -u root stable apt install -o APT::Install-Suggests=false -qy ${release} \
libgps-dev:arm64 \ libgps-dev:arm64 \
libgps-dev:armhf libgps-dev:armhf \
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 -DENABLE_GPS=ON -B build-${cc} podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=${cc} -DENABLE_WERROR=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 -DENABLE_GPS=ON -B build-${cc} podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=${cc} -DENABLE_WERROR=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
gps: ${{ matrix.release == 'ubuntu:20.04' && 'OFF' || 'ON' }}
run: | run: |
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=cmake/${toolchain}.cmake -DENABLE_WERROR=ON -DENABLE_GPS=${gps} -B build-${toolchain} 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 --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
if: if:
matrix.release != 'ubuntu:20.04' && matrix.release != 'debian:oldstable-slim' ${{ matrix.release != 'ubuntu:20.04' && matrix.release != 'debian:oldstable-slim' }}
env: env:
toolchain: arm-linux-gnueabihf-clang toolchain: arm-linux-gnueabihf-clang
gps: ${{ matrix.release == 'ubuntu:20.04' && 'OFF' || 'ON' }}
run: | run: |
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=cmake/${toolchain}.cmake -DENABLE_WERROR=ON -DENABLE_GPS=${gps} -B build-${toolchain} 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 --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
gps: ${{ matrix.release == 'ubuntu:20.04' && 'OFF' || 'ON' }}
run: | run: |
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=cmake/${toolchain}.cmake -DENABLE_WERROR=ON -DENABLE_GPS=${gps} -B build-${toolchain} 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 --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
if: if:
matrix.release != 'ubuntu:20.04' && matrix.release != 'debian:oldstable-slim' ${{ matrix.release != 'ubuntu:20.04' && matrix.release != 'debian:oldstable-slim' }}
env: env:
toolchain: aarch64-linux-gnu-clang toolchain: aarch64-linux-gnu-clang
gps: ${{ matrix.release == 'ubuntu:20.04' && 'OFF' || 'ON' }}
run: | run: |
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=cmake/${toolchain}.cmake -DENABLE_WERROR=ON -DENABLE_GPS=${gps} -B build-${toolchain} 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 --build build-${toolchain} podman exec -i stable cmake --build build-${toolchain}
- name: Configure & Build with gcc (Makefile) - name: Configure & Build with mips-linux-gnu-gcc
env: env:
cc: gcc toolchain: mips-linux-gnu-gcc
run: | run: |
podman exec -i stable make CC=${cc} 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 make clean podman exec -i stable cmake --build build-${toolchain}
- name: Configure & Build with clang (Makefile)
env:
cc: clang
run: |
podman exec -i stable make CC=${cc}
podman exec -i stable make clean
- name: Show logs - name: Show logs
if: ${{ failure() }} if: ${{ failure() }}
+1 -2
View File
@@ -6,6 +6,7 @@
.ccls-cache .ccls-cache
CMakeCache.txt CMakeCache.txt
CMakeFiles/ CMakeFiles/
Makefile
cmake_install.cmake cmake_install.cmake
compile_commands.json compile_commands.json
tags tags
@@ -16,7 +17,6 @@ tags
/can-calc-bit-timing /can-calc-bit-timing
/canbusload /canbusload
/candump /candump
/canerrsim
/canfdtest /canfdtest
/cangen /cangen
/cangw /cangw
@@ -40,7 +40,6 @@ tags
/j1939sr /j1939sr
/j1939-timedate-cli /j1939-timedate-cli
/j1939-timedate-srv /j1939-timedate-srv
/j1939-vehicle-position-srv
/log2asc /log2asc
/log2long /log2long
/mcp251xfd-dump /mcp251xfd-dump
+116 -140
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.5...3.10) cmake_minimum_required(VERSION 3.5)
project(can-utils LANGUAGES C) project(can-utils LANGUAGES C)
@@ -12,38 +12,8 @@ if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release) set(CMAKE_BUILD_TYPE Release)
endif() endif()
if(CMAKE_EXPORT_COMPILE_COMMANDS STREQUAL "")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE BOOL "project default" FORCE)
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)
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
# Options for controlling targets. These groups correspond to the README.
option(ENABLE_BASIC_TOOLS "Build basic tools" ON)
option(ENABLE_IP_SERVER "Build tools providing CAN access via IP sockets" ON)
option(ENABLE_GATEWAY "Build in-kernel gateway configuration tools" ON)
option(ENABLE_MEASUREMENT "Build measurement tools" ON)
option(ENABLE_ISOTP "Build isotp tools" ON)
option(ENABLE_LOG_FILE "Build log file converter tools" ON)
option(ENABLE_SLCAN "Build slcan tools" ON)
option(ENABLE_MCP251XFD "Build MCP251XFD tools" ON)
# cmake_dependent_option is only available in CMake 3.22 and later.
if(ANDROID)
set(ENABLE_J1939 OFF)
set(ENABLE_ISOBUSFS OFF)
else()
option(ENABLE_J1939 "Build J1939 tools" ON)
option(ENABLE_ISOBUSFS "Build ISOBUS tools" ON)
endif()
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,64 +37,24 @@ include_directories(./include)
check_function_exists(fork HAVE_FORK) check_function_exists(fork HAVE_FORK)
# List of all programs to be built. set(PROGRAMS_CANLIB
# Each program is expected to have a corresponding source file with the same name. asc2log
set(PROGRAMS) canbusload
# List of programs to link against can.
set(PROGRAMS_CANLIB)
# List of programs to link against j1939 and can.
set(PROGRAMS_J1939)
if(ENABLE_BASIC_TOOLS)
list(APPEND PROGRAMS cansniffer)
list(APPEND PROGRAMS_CANLIB
candump candump
cangen
canplayer canplayer
cansend cansend
cangen
cansequence cansequence
) log2asc
endif() log2long
slcanpty
if(ENABLE_IP_SERVER AND HAVE_FORK)
list(APPEND PROGRAMS bcmserver)
list(APPEND PROGRAMS_CANLIB canlogserver)
endif()
if(ENABLE_GATEWAY)
list(APPEND PROGRAMS cangw)
endif()
if(ENABLE_MEASUREMENT)
list(APPEND PROGRAMS
canfdtest
canerrsim
)
list(APPEND PROGRAMS_CANLIB canbusload)
add_executable(can-calc-bit-timing
calc-bit-timing/can-calc-bit-timing.c
)
install(TARGETS can-calc-bit-timing DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
if(ENABLE_ISOTP)
list(APPEND PROGRAMS
isotpdump
isotpperf
isotprecv
isotpsend
isotpsniffer
isotptun
) )
if(HAVE_FORK) if(HAVE_FORK)
list(APPEND PROGRAMS isotpserver) list(APPEND PROGRAMS_CANLIB canlogserver)
endif()
endif() endif()
if(ENABLE_J1939) set(PROGRAMS_J1939
list(APPEND PROGRAMS_J1939
j1939acd j1939acd
j1939cat j1939cat
j1939spy j1939spy
@@ -132,46 +62,77 @@ if(ENABLE_J1939)
testj1939 testj1939
) )
add_executable(j1939-timedate-cli set(PROGRAMS_J1939_TIMEDATE
j1939_timedate/j1939_timedate_cli.c j1939-timedate-srv
j1939-timedate-cli
) )
target_link_libraries(j1939-timedate-cli
PRIVATE can j1939
)
install(TARGETS j1939-timedate-cli DESTINATION ${CMAKE_INSTALL_BINDIR})
add_executable(j1939-timedate-srv set(PROGRAMS_J1939_VEHICLE_POSITION
j1939_timedate/j1939_timedate_srv.c j1939-vehicle-position-srv
) )
target_link_libraries(j1939-timedate-srv
PRIVATE can j1939 set(PROGRAMS_ISOBUSFS
isobusfs-srv
isobusfs-cli
) )
install(TARGETS j1939-timedate-srv DESTINATION ${CMAKE_INSTALL_BINDIR})
set(PROGRAMS
${PROGRAMS_CANLIB}
canfdtest
cangw
cansniffer
isotpdump
isotpperf
isotprecv
isotpsend
isotpsniffer
isotptun
slcan_attach
slcand
)
if(HAVE_FORK)
list(APPEND PROGRAMS bcmserver)
list(APPEND PROGRAMS isotpserver)
endif() endif()
if(ENABLE_J1939 AND ENABLE_GPS) add_executable(can-calc-bit-timing
add_executable(j1939-vehicle-position-srv calc-bit-timing/can-calc-bit-timing.c
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()
if(ENABLE_ISOBUSFS) add_executable(mcp251xfd-dump
add_library(isobusfs EXCLUDE_FROM_ALL mcp251xfd/mcp251xfd-dev-coredump.c
mcp251xfd/mcp251xfd-dump.c
mcp251xfd/mcp251xfd-main.c
mcp251xfd/mcp251xfd-regmap.c
)
if(NOT ANDROID)
list(APPEND PROGRAMS ${PROGRAMS_J1939})
add_library(j1939 STATIC
libj1939.c
)
target_link_libraries(j1939
PRIVATE can
)
add_library(isobusfs SHARED
isobusfs/isobusfs_cmn.c isobusfs/isobusfs_cmn.c
isobusfs/isobusfs_cmn_dh.c isobusfs/isobusfs_cmn_dh.c
) )
set(PUBLIC_HEADER_ISOBUSFS set(PUBLIC_HEADER_ISOBUSFS
isobusfs/isobusfs_cmn.h isobusfs/isobusfs_cmn.h
isobusfs/isobusfs_cmn_cm.h isobusfs/isobusfs_cmn_cm.h
) )
set_target_properties(isobusfs PROPERTIES set_target_properties(isobusfs PROPERTIES
PUBLIC_HEADER "${PUBLIC_HEADER_ISOBUSFS}" PUBLIC_HEADER "${PUBLIC_HEADER_ISOBUSFS}"
SOVERSION 0 SOVERSION 0
) )
install(TARGETS isobusfs install(TARGETS isobusfs
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
@@ -185,10 +146,10 @@ if(ENABLE_ISOBUSFS)
isobusfs/isobusfs_cli_selftests.c isobusfs/isobusfs_cli_selftests.c
isobusfs/isobusfs_cli_int.c isobusfs/isobusfs_cli_int.c
) )
target_link_libraries(isobusfs-cli target_link_libraries(isobusfs-cli
PRIVATE isobusfs can j1939 PRIVATE isobusfs can j1939
) )
install(TARGETS isobusfs-cli DESTINATION ${CMAKE_INSTALL_BINDIR})
add_executable(isobusfs-srv add_executable(isobusfs-srv
isobusfs/isobusfs_srv.c isobusfs/isobusfs_srv.c
@@ -199,55 +160,64 @@ if(ENABLE_ISOBUSFS)
isobusfs/isobusfs_srv_fh.c isobusfs/isobusfs_srv_fh.c
isobusfs/isobusfs_srv_vh.c isobusfs/isobusfs_srv_vh.c
) )
target_link_libraries(isobusfs-srv target_link_libraries(isobusfs-srv
PRIVATE isobusfs can j1939 PRIVATE isobusfs can j1939
) )
install(TARGETS isobusfs-srv DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
if(ENABLE_LOG_FILE) install(TARGETS
list(APPEND PROGRAMS_CANLIB isobusfs-cli
asc2log isobusfs-srv
log2asc DESTINATION ${CMAKE_INSTALL_BINDIR})
log2long
)
endif()
if(ENABLE_SLCAN) set(PUBLIC_HEADER_j1939_TIMEDATE
list(APPEND PROGRAMS j1939_timedate/j1939_timedate_cmn.h
slcan_attach
slcand
)
list(APPEND PROGRAMS_CANLIB slcanpty)
endif()
if(ENABLE_MCP251XFD)
add_executable(mcp251xfd-dump
mcp251xfd/mcp251xfd-dev-coredump.c
mcp251xfd/mcp251xfd-dump.c
mcp251xfd/mcp251xfd-main.c
mcp251xfd/mcp251xfd-regmap.c
)
install(TARGETS mcp251xfd-dump DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
list(APPEND PROGRAMS
${PROGRAMS_CANLIB}
${PROGRAMS_J1939}
) )
add_library(can STATIC EXCLUDE_FROM_ALL add_executable(j1939-timedate-cli
j1939_timedate/j1939_timedate_cli.c
)
target_link_libraries(j1939-timedate-cli
PRIVATE can j1939
)
add_executable(j1939-timedate-srv
j1939_timedate/j1939_timedate_srv.c
)
target_link_libraries(j1939-timedate-srv
PRIVATE can j1939
)
install(TARGETS
j1939-timedate-cli
j1939-timedate-srv
DESTINATION ${CMAKE_INSTALL_BINDIR})
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
)
install(TARGETS
j1939-vehicle-position-srv
DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
add_library(can STATIC
lib.c lib.c
canframelen.c canframelen.c
) )
add_library(j1939 STATIC EXCLUDE_FROM_ALL
libj1939.c
)
target_link_libraries(j1939
PRIVATE can
)
foreach(name ${PROGRAMS}) foreach(name ${PROGRAMS})
add_executable(${name} ${name}.c) add_executable(${name} ${name}.c)
@@ -264,6 +234,12 @@ foreach(name ${PROGRAMS})
install(TARGETS ${name} DESTINATION ${CMAKE_INSTALL_BINDIR}) install(TARGETS ${name} DESTINATION ${CMAKE_INSTALL_BINDIR})
endforeach() endforeach()
install(TARGETS
can-calc-bit-timing
mcp251xfd-dump
DESTINATION ${CMAKE_INSTALL_BINDIR}
)
add_custom_target(uninstall add_custom_target(uninstall
"${CMAKE_COMMAND}" -P "${CMAKE_SOURCE_DIR}/cmake/make_uninstall.cmake" "${CMAKE_COMMAND}" -P "${CMAKE_SOURCE_DIR}/cmake/make_uninstall.cmake"
COMMENT "Add uninstall target" COMMENT "Add uninstall target"
+2 -6
View File
@@ -46,7 +46,6 @@ MAKEFLAGS := -k
CFLAGS := -O2 -Wall -Wno-parentheses -Wsign-compare CFLAGS := -O2 -Wall -Wno-parentheses -Wsign-compare
HAVE_FORK := $(shell ./check_cc.sh "$(CC)" fork_test.c) HAVE_FORK := $(shell ./check_cc.sh "$(CC)" fork_test.c)
HAVE_LIBGPS := $(shell test -x "`which pkg-config`" && pkg-config --exists libgps && echo 1 || echo 0)
CPPFLAGS += \ CPPFLAGS += \
-I. \ -I. \
@@ -68,10 +67,8 @@ PROGRAMS_J1939_TIMEDATE := \
j1939-timedate-srv \ j1939-timedate-srv \
j1939-timedate-cli j1939-timedate-cli
ifeq ($(HAVE_LIBGPS),1)
PROGRAMS_J1939_VEHICLE_POSITION := \ PROGRAMS_J1939_VEHICLE_POSITION := \
j1939-vehicle-position-srv j1939-vehicle-position-srv
endif
PROGRAMS_ISOBUSFS := \ PROGRAMS_ISOBUSFS := \
isobusfs-srv \ isobusfs-srv \
@@ -113,7 +110,6 @@ PROGRAMS := \
can-calc-bit-timing \ can-calc-bit-timing \
canbusload \ canbusload \
candump \ candump \
canerrsim \
canfdtest \ canfdtest \
cangen \ cangen \
cansequence \ cansequence \
@@ -196,8 +192,8 @@ j1939-timedate-cli: lib.o \
j1939-vehicle-position-srv: \ j1939-vehicle-position-srv: \
lib.o \ lib.o \
libj1939.o \ libj1939.o \
j1939_vehicle_position/j1939_vehicle_position_srv.o j1939_vehicle_position/j1939_vehicle_position_srv.o \
$(CC) $(LDFLAGS) $^ $(LDLIBS) $(shell pkg-config --libs libgps) -o $@ $(CC) $(LDFLAGS) $^ $(LDLIBS) -lgps -o $@
isobusfs-srv: lib.o \ isobusfs-srv: lib.o \
libj1939.o \ libj1939.o \
+1 -6
View File
@@ -29,7 +29,6 @@ subsystem (aka SocketCAN):
* canbusload : calculate and display the CAN busload * canbusload : calculate and display the CAN busload
* can-calc-bit-timing : userspace version of in-kernel bitrate calculation * can-calc-bit-timing : userspace version of in-kernel bitrate calculation
* canfdtest : Full-duplex test program (DUT and host part) * canfdtest : Full-duplex test program (DUT and host part)
* canerrsim : CAN error message simulator
#### ISO-TP tools [ISO15765-2:2016 for Linux](https://github.com/hartkopp/can-isotp) #### ISO-TP tools [ISO15765-2:2016 for Linux](https://github.com/hartkopp/can-isotp)
* isotpsend : send a single ISO-TP PDU * isotpsend : send a single ISO-TP PDU
@@ -50,10 +49,6 @@ subsystem (aka SocketCAN):
Follow the link to see examples on how this tools can be used: Follow the link to see examples on how this tools can be used:
[Kickstart guide to can-j1939 on linux](https://github.com/linux-can/can-utils/blob/master/can-j1939-kickstart.md) [Kickstart guide to can-j1939 on linux](https://github.com/linux-can/can-utils/blob/master/can-j1939-kickstart.md)
#### ISOBus File server tools
* isobusfs-cli : ISOBus file client
* isobusfs-srv : ISOBus file server
#### Log file converters #### Log file converters
* asc2log : convert ASC logfile to compact CAN frame logfile * asc2log : convert ASC logfile to compact CAN frame logfile
* log2asc : convert compact CAN frame logfile to ASC logfile * log2asc : convert compact CAN frame logfile to ASC logfile
@@ -80,4 +75,4 @@ Follow the link to see examples on how this tools can be used:
* [SocketCAN Documentation (Linux Kernel)](https://www.kernel.org/doc/html/latest/networking/can.html) * [SocketCAN Documentation (Linux Kernel)](https://www.kernel.org/doc/html/latest/networking/can.html)
* [Elinux.org CAN Bus Page](http://elinux.org/CAN_Bus) * [Elinux.org CAN Bus Page](http://elinux.org/CAN_Bus)
* [Debian Package Description](https://packages.debian.org/sid/can-utils) * [Debian Package Description](https://packages.debian.org/sid/can-utils)
* [J1939 kernel module installation on Debian](can-j1939-install-kernel-module.md)
+7 -7
View File
@@ -84,7 +84,7 @@ static void print_usage(char *prg)
} }
static void prframe(FILE *file, struct timeval *tv, int dev, static void prframe(FILE *file, struct timeval *tv, int dev,
union cfu *cf, char dir) cu_t *cf, char dir)
{ {
static char abuf[BUFLEN]; static char abuf[BUFLEN];
@@ -177,7 +177,7 @@ static void eval_can(char* buf, struct timeval *date_tvp, char timestamps,
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, (union cfu *)&cf, NO_DIR); prframe(outfile, &tv, interface, (cu_t *)&cf, NO_DIR);
fflush(outfile); fflush(outfile);
return; return;
} }
@@ -249,7 +249,7 @@ 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, (union cfu *)&cf, dir[0]); prframe(outfile, &tv, interface, (cu_t *)&cf, dir[0]);
fflush(outfile); fflush(outfile);
} }
} }
@@ -374,7 +374,7 @@ 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, (union cfu *)&cf, dir[0]); 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( */
@@ -487,7 +487,7 @@ static void eval_canxl_cc(char* buf, struct timeval *date_tvp, char timestamps,
cf.len8_dlc = dlc; cf.len8_dlc = dlc;
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace); calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
prframe(outfile, &tv, interface, (union cfu *)&cf, dir[0]); prframe(outfile, &tv, interface, (cu_t *)&cf, dir[0]);
fflush(outfile); fflush(outfile);
} }
@@ -594,7 +594,7 @@ static void eval_canxl_fd(char* buf, struct timeval *date_tvp, char timestamps,
cf.flags |= CANFD_ESI; cf.flags |= CANFD_ESI;
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace); calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
prframe(outfile, &tv, interface, (union cfu *)&cf, dir[0]); prframe(outfile, &tv, interface, (cu_t *)&cf, dir[0]);
fflush(outfile); fflush(outfile);
} }
@@ -723,7 +723,7 @@ static void eval_canxl_xl(char* buf, struct timeval *date_tvp, char timestamps,
cf.flags |= CANXL_RRS; cf.flags |= CANXL_RRS;
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace); calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
prframe(outfile, &tv, interface, (union cfu *)&cf, dir[0]); prframe(outfile, &tv, interface, (cu_t *)&cf, dir[0]);
fflush(outfile); fflush(outfile);
/* No support for CAN XL ErrorFrames */ /* No support for CAN XL ErrorFrames */
+8 -28
View File
@@ -153,7 +153,7 @@ int main(void)
char buf[MAXLEN]; char buf[MAXLEN];
char format[FORMATSZ]; char format[FORMATSZ];
char rxmsg[64]; char rxmsg[50];
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpragmas" #pragma GCC diagnostic ignored "-Wpragmas"
@@ -234,7 +234,7 @@ int main(void)
} }
while (1) { while (1) {
again:
FD_ZERO(&readfds); FD_ZERO(&readfds);
FD_SET(sc, &readfds); FD_SET(sc, &readfds);
FD_SET(sa, &readfds); FD_SET(sa, &readfds);
@@ -242,8 +242,6 @@ again:
select((sc > sa)?sc+1:sa+1, &readfds, NULL, NULL, NULL); select((sc > sa)?sc+1:sa+1, &readfds, NULL, NULL, NULL);
if (FD_ISSET(sc, &readfds)) { if (FD_ISSET(sc, &readfds)) {
size_t size = sizeof(rxmsg);
int len = 0, res;
recvfrom(sc, &msg, sizeof(msg), 0, recvfrom(sc, &msg, sizeof(msg), 0,
(struct sockaddr*)&caddr, &caddrlen); (struct sockaddr*)&caddr, &caddrlen);
@@ -251,35 +249,17 @@ again:
ifr.ifr_ifindex = caddr.can_ifindex; ifr.ifr_ifindex = caddr.can_ifindex;
ioctl(sc, SIOCGIFNAME, &ifr); ioctl(sc, SIOCGIFNAME, &ifr);
res = snprintf(rxmsg, size, "< %s %03X %d ", ifr.ifr_name, sprintf(rxmsg, "< %s %03X %d ", ifr.ifr_name,
msg.msg_head.can_id, msg.frame.can_dlc); msg.msg_head.can_id, msg.frame.can_dlc);
if (res < 0 || (size_t)res >= size) {
printf("Error: rxmsg buffer (size %zu) too small for data.\n", size);
continue;
}
len += res; for ( i = 0; i < msg.frame.can_dlc; i++)
sprintf(rxmsg + strlen(rxmsg), "%02X ",
for (i = 0; i < msg.frame.can_dlc; i++) { msg.frame.data[i]);
res = snprintf(rxmsg + len, size - len, "%02X ", msg.frame.data[i]);
if (res < 0 || (size_t)res >= (size - len)) {
printf("Error: rxmsg buffer (size %zu) too small for data.\n", size);
goto again;
}
len += res;
}
/* delimiter '\0' for Adobe(TM) Flash(TM) XML sockets */ /* delimiter '\0' for Adobe(TM) Flash(TM) XML sockets */
res = snprintf(rxmsg + len, size - len, ">"); strcat(rxmsg, ">\0");
if (res < 0 || (size_t)res >= (size - len)) {
printf("Error: rxmsg buffer (size %zu) too small for data.\n", size);
continue;
}
len += res; send(sa, rxmsg, strlen(rxmsg) + 1, 0);
send(sa, rxmsg, len + 1, 0);
} }
-5
View File
@@ -1121,11 +1121,6 @@ static const unsigned int common_data_bitrates[] = {
4000000, 4000000,
2000000, 2000000,
1000000, 1000000,
800000,
500000,
250000,
125000,
100000,
0 0
}; };
+36 -69
View File
@@ -72,9 +72,6 @@
#ifndef SO_TIMESTAMPING #ifndef SO_TIMESTAMPING
#define SO_TIMESTAMPING 37 #define SO_TIMESTAMPING 37
#endif #endif
#ifndef SCM_TIMESTAMPING
#define SCM_TIMESTAMPING SO_TIMESTAMPING
#endif
#define TIMESTAMPSZ 50 /* string 'absolute with date' requires max 49 bytes */ #define TIMESTAMPSZ 50 /* string 'absolute with date' requires max 49 bytes */
@@ -116,8 +113,7 @@ static const int canfx_on = 1;
#define MAXANI 4 #define MAXANI 4
static const char anichar[MAXANI] = { '|', '/', '-', '\\' }; static const char anichar[MAXANI] = { '|', '/', '-', '\\' };
static const char extra_fd_info[4][4] = { "- -", "B -", "- E", "B E" }; static const char extra_m_info[4][4] = { "- -", "B -", "- E", "B E" };
static const char extra_xl_info[4][4] = { "- -", "S -", "- R", "S R" };
extern int optind, opterr, optopt; extern int optind, opterr, optopt;
@@ -132,7 +128,6 @@ static void print_usage(void)
fprintf(stderr, "Options:\n"); fprintf(stderr, "Options:\n");
fprintf(stderr, " -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n"); fprintf(stderr, " -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n");
fprintf(stderr, " -H (read hardware timestamps instead of system timestamps)\n"); fprintf(stderr, " -H (read hardware timestamps instead of system timestamps)\n");
fprintf(stderr, " -N (log nanosecond timestamps instead of microseconds)\n");
fprintf(stderr, " -c (increment color mode level)\n"); fprintf(stderr, " -c (increment color mode level)\n");
fprintf(stderr, " -i (binary output - may exceed 80 chars/line)\n"); fprintf(stderr, " -i (binary output - may exceed 80 chars/line)\n");
fprintf(stderr, " -a (enable additional ASCII output)\n"); fprintf(stderr, " -a (enable additional ASCII output)\n");
@@ -147,7 +142,7 @@ static void print_usage(void)
fprintf(stderr, " -d (monitor dropped CAN frames)\n"); fprintf(stderr, " -d (monitor dropped CAN frames)\n");
fprintf(stderr, " -e (dump CAN error frames in human-readable format)\n"); fprintf(stderr, " -e (dump CAN error frames in human-readable format)\n");
fprintf(stderr, " -8 (display raw DLC values in {} for Classical CAN)\n"); fprintf(stderr, " -8 (display raw DLC values in {} for Classical CAN)\n");
fprintf(stderr, " -x (print extra message infos, rx/tx [brs esi|sec rrs])\n"); fprintf(stderr, " -x (print extra message infos, rx/tx brs esi)\n");
fprintf(stderr, " -T <msecs> (terminate after <msecs> if no frames were received)\n"); fprintf(stderr, " -T <msecs> (terminate after <msecs> if no frames were received)\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "Up to %d CAN interfaces with optional filter sets can be specified\n", MAXSOCK); fprintf(stderr, "Up to %d CAN interfaces with optional filter sets can be specified\n", MAXSOCK);
@@ -225,22 +220,16 @@ static int idx2dindex(int ifidx, int socket)
return i; return i;
} }
static int sprint_timestamp(char *ts_buffer, const char timestamp, const char use_ns, static int sprint_timestamp(char *ts_buffer, const char timestamp,
const struct timespec *ts, struct timespec *const last_ts) const struct timeval *tv, struct timeval *const last_tv)
{ {
int numchars = 0; int numchars = 0;
switch (timestamp) { switch (timestamp) {
case 'a': /* absolute with timestamp */ case 'a': /* absolute with timestamp */
if (use_ns) {
numchars = sprintf(ts_buffer, "(%010llu.%09llu) ",
(unsigned long long)ts->tv_sec,
(unsigned long long)ts->tv_nsec);
} else {
numchars = sprintf(ts_buffer, "(%010llu.%06llu) ", numchars = sprintf(ts_buffer, "(%010llu.%06llu) ",
(unsigned long long)ts->tv_sec, (unsigned long long)tv->tv_sec,
(unsigned long long)ts->tv_nsec / 1000); (unsigned long long)tv->tv_usec);
}
break; break;
case 'A': /* absolute with date */ case 'A': /* absolute with date */
@@ -248,43 +237,32 @@ static int sprint_timestamp(char *ts_buffer, const char timestamp, const char us
struct tm tm; struct tm tm;
char timestring[25]; char timestring[25];
tm = *localtime(&ts->tv_sec); tm = *localtime(&tv->tv_sec);
strftime(timestring, 24, "%Y-%m-%d %H:%M:%S", &tm); strftime(timestring, 24, "%Y-%m-%d %H:%M:%S", &tm);
if (use_ns) {
numchars = sprintf(ts_buffer, "(%s.%09llu) ", timestring,
(unsigned long long)ts->tv_nsec);
} else {
numchars = sprintf(ts_buffer, "(%s.%06llu) ", timestring, numchars = sprintf(ts_buffer, "(%s.%06llu) ", timestring,
(unsigned long long)ts->tv_nsec / 1000); (unsigned long long)tv->tv_usec);
}
} }
break; break;
case 'd': /* delta */ case 'd': /* delta */
case 'z': /* starting with zero */ case 'z': /* starting with zero */
{ {
struct timespec diff; struct timeval diff;
if (last_ts->tv_sec == 0) /* first init */ if (last_tv->tv_sec == 0) /* first init */
*last_ts = *ts; *last_tv = *tv;
diff.tv_sec = ts->tv_sec - last_ts->tv_sec; diff.tv_sec = tv->tv_sec - last_tv->tv_sec;
diff.tv_nsec = ts->tv_nsec - last_ts->tv_nsec; diff.tv_usec = tv->tv_usec - last_tv->tv_usec;
if (diff.tv_nsec < 0) if (diff.tv_usec < 0)
diff.tv_sec--, diff.tv_nsec += 1000000000; diff.tv_sec--, diff.tv_usec += 1000000;
if (diff.tv_sec < 0) if (diff.tv_sec < 0)
diff.tv_sec = diff.tv_nsec = 0; diff.tv_sec = diff.tv_usec = 0;
if (use_ns) {
numchars = sprintf(ts_buffer, "(%03llu.%09llu) ",
(unsigned long long)diff.tv_sec,
(unsigned long long)diff.tv_nsec);
} else {
numchars = sprintf(ts_buffer, "(%03llu.%06llu) ", numchars = sprintf(ts_buffer, "(%03llu.%06llu) ",
(unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_sec,
(unsigned long long)diff.tv_nsec / 1000); (unsigned long long)diff.tv_usec);
}
if (timestamp == 'd') if (timestamp == 'd')
*last_ts = *ts; /* update for delta calculation */ *last_tv = *tv; /* update for delta calculation */
} }
break; break;
@@ -310,7 +288,6 @@ int main(int argc, char **argv)
unsigned char timestamp = 0; unsigned char timestamp = 0;
unsigned char logtimestamp = 'a'; unsigned char logtimestamp = 'a';
unsigned char hwtimestamp = 0; unsigned char hwtimestamp = 0;
unsigned char use_ns = 0;
unsigned char down_causes_exit = 1; unsigned char down_causes_exit = 1;
unsigned char dropmonitor = 0; unsigned char dropmonitor = 0;
unsigned char extra_msg_info = 0; unsigned char extra_msg_info = 0;
@@ -342,10 +319,10 @@ int main(int argc, char **argv)
struct cmsghdr *cmsg; struct cmsghdr *cmsg;
struct can_filter *rfilter; struct can_filter *rfilter;
can_err_mask_t err_mask; can_err_mask_t err_mask;
static union cfu cu; /* union for CAN CC/FD/XL frames */ static cu_t cu; /* union for CAN CC/FD/XL frames */
int nbytes, i; int nbytes, i;
struct ifreq ifr; struct ifreq ifr;
struct timespec ts, last_ts; struct timeval tv, last_tv;
int timeout_ms = -1; /* default to no timeout */ int timeout_ms = -1; /* default to no timeout */
FILE *logfile = NULL; FILE *logfile = NULL;
char fname[83]; /* suggested by -Wformat-overflow= */ char fname[83]; /* suggested by -Wformat-overflow= */
@@ -357,12 +334,12 @@ int main(int argc, char **argv)
signal(SIGHUP, sigterm); signal(SIGHUP, sigterm);
signal(SIGINT, sigterm); signal(SIGINT, sigterm);
last_ts.tv_sec = 0; last_tv.tv_sec = 0;
last_ts.tv_nsec = 0; last_tv.tv_usec = 0;
progname = basename(argv[0]); progname = basename(argv[0]);
while ((opt = getopt(argc, argv, "t:HNciaSs:lf:Ln:r:Dde8xT:h?")) != -1) { while ((opt = getopt(argc, argv, "t:HciaSs:lf:Ln:r:Dde8xT:h?")) != -1) {
switch (opt) { switch (opt) {
case 't': case 't':
timestamp = optarg[0]; timestamp = optarg[0];
@@ -382,10 +359,6 @@ int main(int argc, char **argv)
hwtimestamp = 1; hwtimestamp = 1;
break; break;
case 'N':
use_ns = 1;
break;
case 'c': case 'c':
color++; color++;
break; break;
@@ -810,13 +783,9 @@ int main(int argc, char **argv)
for (cmsg = CMSG_FIRSTHDR(&msg); for (cmsg = CMSG_FIRSTHDR(&msg);
cmsg && (cmsg->cmsg_level == SOL_SOCKET); cmsg && (cmsg->cmsg_level == SOL_SOCKET);
cmsg = CMSG_NXTHDR(&msg,cmsg)) { cmsg = CMSG_NXTHDR(&msg,cmsg)) {
if (cmsg->cmsg_type == SCM_TIMESTAMP) { if (cmsg->cmsg_type == SO_TIMESTAMP) {
struct timeval tv;
memcpy(&tv, CMSG_DATA(cmsg), sizeof(tv)); memcpy(&tv, CMSG_DATA(cmsg), sizeof(tv));
ts.tv_sec = tv.tv_sec; } else if (cmsg->cmsg_type == SO_TIMESTAMPING) {
ts.tv_nsec = tv.tv_usec;
ts.tv_nsec *= 1000;
} else if (cmsg->cmsg_type == SCM_TIMESTAMPING) {
struct timespec *stamp = (struct timespec *)CMSG_DATA(cmsg); struct timespec *stamp = (struct timespec *)CMSG_DATA(cmsg);
/* /*
@@ -826,7 +795,8 @@ int main(int argc, char **argv)
* See chapter 2.1.2 Receive timestamps in * See chapter 2.1.2 Receive timestamps in
* linux/Documentation/networking/timestamping.txt * linux/Documentation/networking/timestamping.txt
*/ */
ts = stamp[2]; tv.tv_sec = stamp[2].tv_sec;
tv.tv_usec = stamp[2].tv_nsec / 1000;
} else if (cmsg->cmsg_type == SO_RXQ_OVFL) { } else if (cmsg->cmsg_type == SO_RXQ_OVFL) {
memcpy(&obj->dropcnt, CMSG_DATA(cmsg), sizeof(__u32)); memcpy(&obj->dropcnt, CMSG_DATA(cmsg), sizeof(__u32));
} }
@@ -861,9 +831,11 @@ int main(int argc, char **argv)
/* build common log format output */ /* build common log format output */
if ((log) || ((logfrmt) && (silent == SILENT_OFF))) { if ((log) || ((logfrmt) && (silent == SILENT_OFF))) {
alen = sprint_timestamp(afrbuf, logtimestamp, use_ns, &ts, &last_ts); alen = sprint_timestamp(afrbuf, logtimestamp,
&tv, &last_tv);
alen += sprintf(afrbuf + alen, "%*s ", max_devname_len, devname[idx]); alen += sprintf(afrbuf + alen, "%*s ",
max_devname_len, devname[idx]);
alen += snprintf_canframe(afrbuf + alen, sizeof(afrbuf) - alen, &cu, 0); alen += snprintf_canframe(afrbuf + alen, sizeof(afrbuf) - alen, &cu, 0);
} }
@@ -889,23 +861,18 @@ int main(int argc, char **argv)
/* print (colored) long CAN frame style to stdout */ /* print (colored) long CAN frame style to stdout */
alen = sprintf(afrbuf, " %s", (color > 2) ? col_on[idx % MAXCOL] : ""); alen = sprintf(afrbuf, " %s", (color > 2) ? col_on[idx % MAXCOL] : "");
alen += sprint_timestamp(afrbuf + alen, timestamp, use_ns, &ts, &last_ts); alen += sprint_timestamp(afrbuf + alen, timestamp, &tv, &last_tv);
alen += sprintf(afrbuf + alen, " %s%*s", alen += sprintf(afrbuf + alen, " %s%*s",
(color && (color < 3)) ? col_on[idx % MAXCOL] : "", (color && (color < 3)) ? col_on[idx % MAXCOL] : "",
max_devname_len, devname[idx]); max_devname_len, devname[idx]);
if (extra_msg_info) { if (extra_msg_info) {
if (msg.msg_flags & MSG_DONTROUTE) if (msg.msg_flags & MSG_DONTROUTE)
alen += sprintf(afrbuf + alen, " TX"); alen += sprintf(afrbuf + alen, " TX %s",
extra_m_info[cu.fd.flags & 3]);
else else
alen += sprintf(afrbuf + alen, " RX"); alen += sprintf(afrbuf + alen, " RX %s",
extra_m_info[cu.fd.flags & 3]);
if (cu.xl.flags & CANXL_XLF)
alen += sprintf(afrbuf + alen, " %s",
extra_xl_info[cu.xl.flags & 3]);
else
alen += sprintf(afrbuf + alen, " %s",
extra_fd_info[cu.fd.flags & 3]);
} }
alen += sprintf(afrbuf + alen, "%s ", (color == 1) ? col_off : ""); alen += sprintf(afrbuf + alen, "%s ", (color == 1) ? col_off : "");
-563
View File
@@ -1,563 +0,0 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// canerrsim - utility to simulate SocketCAN error messages, by Zeljko Avramovic (c) 2024 //
// //
// SPDX-License-Identifier: LGPL-2.1-or-later OR BSD-3-Clause //
// //
// Virtual CAN adapter vcan0 is hard coded and you can bring it up like this: //
// sudo modprobe vcan //
// sudo ip link add dev vcan0 type vcan //
// sudo ip link set vcan0 mtu 72 # needed for CAN FD //
// sudo ip link set vcan0 up //
// //
// To simulate error messages use canerrsim utility like this: //
// ./canerrsim vcan0 LostArBit=09 Data4=AA TX BusOff NoAck ShowBits //
// //
// That should show in canerrdump utility as: //
// 0x06A [8] 09 00 80 00 AA 00 00 00 ERR=LostArBit09,NoAck,BusOff,Prot(Type(TX),Loc(Unspec)) //
// //
// Alternatively, you could use candump from can-utils to check only error messages like this: //
// candump -tA -e -c -a any,0~0,#FFFFFFFF //
// //
////////////////////////////////////////////////////////////////////////////////////////////////////
#include <linux/can.h>
#include <linux/can/error.h>
#include <linux/can/raw.h>
#include <net/if.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#define STR_EQUAL 0
void show_help_and_exit()
{
printf("\n");
printf("Usage: canerrsim <CAN interface> <options>\n");
printf("\n");
printf("CAN interface: ( CAN interface is case sensitive )\n");
printf(" can0 ( or can1, can2 or virtual ones like vcan0, vcan1...\n");
printf("\n");
printf("Options: ( options are not case sensitive )\n");
printf(" ( ERROR CLASS (MASK) IN CAN ID: )\n");
printf(" TxTimeout ( TX timeout by netdevice driver )\n");
printf(" NoAck ( received no ACK on transmission )\n");
printf(" BusOff ( bus off )\n");
printf(" BusError ( bus error, may flood! )\n");
printf(" Restarted ( controller restarted )\n");
printf(" TxCount=<00..FF> ( TX error counter )\n");
printf(" RxCount=<00..FF> ( RX error counter )\n");
printf(" ( ARBITRATIONLOST IN CAN ID + BIT NUMBER IN DATA[0]: )\n");
printf(" LostArBit=<00..29> ( decimal lost arbitration bit number in bitstream )\n");
printf(" ( CONTROLLER IN CAN ID + ERROR STATUS IN DATA[1]: )\n");
printf(" OverflowRX ( RX buffer overflow )\n");
printf(" OverflowTX ( TX buffer overflow )\n");
printf(" WarningRX ( reached warning level for RX errors )\n");
printf(" WarningTX ( reached warning level for TX errors )\n");
printf(" PassiveRX ( reached error passive status RX, errors > 127 )\n");
printf(" PassiveTX ( reached error passive status TX, errors > 127 )\n");
printf(" Active ( recovered to error active state )\n");
printf(" ( PROTOCOL ERROR IN CAN ID + TYPE IN DATA[2]: )\n");
printf(" SingleBit ( single bit error )\n");
printf(" FrameFormat ( frame format error )\n");
printf(" BitStuffing ( bit stuffing error )\n");
printf(" Bit0 ( unable to send dominant bit )\n");
printf(" Bit1 ( unable to send recessive bit )\n");
printf(" BusOverload ( bus overload )\n");
printf(" ActiveAnnouncement ( active error announcement )\n");
printf(" TX ( error occurred on transmission )\n");
printf(" ( PROTOCOL ERROR IN CAN ID + LOCATION IN DATA[3]: )\n");
printf(" SOF ( start of frame )\n");
printf(" ID28_21 ( ID bits 21..28, SFF: 3..10 )\n");
printf(" ID20_18 ( ID bits 18..20, SFF: 0..2 )\n");
printf(" SRTR ( substitute RTR, SFF: RTR )\n");
printf(" IDE ( identifier extension )\n");
printf(" ID17_13 ( ID bits 13..17 )\n");
printf(" ID12_05 ( ID bits 5..12 )\n");
printf(" ID04_00 ( ID bits 0..4 )\n");
printf(" RTR ( RTR )\n");
printf(" RES1 ( reserved bit 1 )\n");
printf(" RES0 ( reserved bit 0 )\n");
printf(" DLC ( data length code )\n");
printf(" DATA ( data section )\n");
printf(" CRC_SEQ ( CRC sequence )\n");
printf(" CRC_DEL ( CRC delimiter )\n");
printf(" ACK ( ACK slot )\n");
printf(" ACK_DEL ( ACK delimiter )\n");
printf(" EOF ( end of frame )\n");
printf(" INTERM ( intermission )\n");
printf(" ( TRANSCEIVER ERROR IN CAN ID + STATUS IN DATA[4]: )\n");
printf(" ( CANH CANL )\n");
printf(" TransUnspec ( 0000 0000 )\n");
printf(" CanHiNoWire ( 0000 0100 )\n");
printf(" CanHiShortToBAT ( 0000 0101 )\n");
printf(" CanHiShortToVCC ( 0000 0110 )\n");
printf(" CanHiShortToGND ( 0000 0111 )\n");
printf(" CanLoNoWire ( 0100 0000 )\n");
printf(" CanLoShortToBAT ( 0101 0000 )\n");
printf(" CanLoShortToVCC ( 0110 0000 )\n");
printf(" CanLoShortToGND ( 0111 0000 )\n");
printf(" CanLoShortToCanHi ( 1000 0000 )\n");
printf(" ( CUSTOM BYTE TO DATA[0..7]: )\n");
printf(" Data<0..7>=<00..FF> ( write hex number to one of 8 payload bytes )\n");
printf(" ( DEBUG HELPERS: )\n");
printf(" ShowBits ( display all frame bits )\n");
printf("\n");
printf("Examples:\n");
printf("\n");
printf(" ./canerrsim can1 LostArBit=09 Data3=AA Data4=BB ShowBits\n");
printf(" ( can1: 9th arb. bit lost, custom bytes in Data[3] and Data[4], show debug frame bits )\n");
printf("\n");
printf(" ./canerrsim vcan0 NoAck TxTimeout Active\n");
printf(" ( vcan0: received no ACK on transmission, driver timeout, protocol type active error announcement )\n");
printf("\n");
printf(" ./canerrsim vcan0 BusError CanHiNoWire Restarted INTERM\n");
printf(" ( vcan0: bus error, lost CANH wiring, controller restarted, protocol location intermission )\n");
printf("\n");
exit(EXIT_SUCCESS);
}
void __attribute__((format (printf, 1, 2))) err_exit(const char *format, ...)
{
va_list ap;
va_start(ap, format);
vfprintf(stdout, format, ap);
va_end(ap);
exit(EXIT_FAILURE);
}
void show_invalid_option(const char *option)
{
err_exit("Error: Invalid option %s\n", option);
}
void show_err_and_exit(const char *err_type)
{
err_exit("Error: You can only have one %s parameter!\n", err_type);
}
void show_loc_err_and_exit()
{
show_err_and_exit("protocol location");
}
void show_arb_err_and_exit()
{
show_err_and_exit("arbitration bit");
}
void show_transc_err_and_exit()
{
show_err_and_exit("transceiver");
}
void print_binary(uint32_t number)
{
uint32_t mask = 0x80000000; // start with the most significant bit
for (int i = 0; i < 32; i++) {
putchar((number & mask) ? '1' : '0');
mask >>= 1; // shift the mask to the right
}
}
int main(int argc, char *argv[])
{
int sock;
struct sockaddr_can addr;
struct ifreq ifr;
struct can_frame frame;
bool show_bits = false, location_processed = false, transceiver_processed = false, arbitration_processed = false;
printf("CAN Sockets Error Messages Simulator\n");
if (argc < 3)
show_help_and_exit();
// initialize CAN frame
memset(&frame, 0, sizeof(frame));
frame.can_id = CAN_ERR_FLAG;
frame.can_dlc = CAN_ERR_DLC;
// Parse command line parameters
for (int i = 2; i < argc; i++) {
//printf("strlen(argv[%d]) = %d\n", i, strlen(argv[i]));
// error class (mask) in can_id
if (strcasecmp(argv[i], "TxTimeout") == STR_EQUAL)
frame.can_id |= CAN_ERR_TX_TIMEOUT; // generate TxTimeout error
else if (strcasecmp(argv[i], "NoAck") == STR_EQUAL)
frame.can_id |= CAN_ERR_ACK; // generate NoAck error
else if (strcasecmp(argv[i], "BusOff") == STR_EQUAL)
frame.can_id |= CAN_ERR_BUSOFF; // generate BusOff error
else if (strcasecmp(argv[i], "BusError") == STR_EQUAL)
frame.can_id |= CAN_ERR_BUSERROR; // generate BusError error
else if (strcasecmp(argv[i], "Restarted") == STR_EQUAL)
frame.can_id |= CAN_ERR_RESTARTED; // generate Restarted error
// error status of CAN controller / data[1]
else if (strcasecmp(argv[i], "OverflowRX") == STR_EQUAL) {
frame.can_id |= CAN_ERR_CRTL; // generate Controller error
frame.data[1] |= CAN_ERR_CRTL_RX_OVERFLOW; // generate RX Overflow suberror
} else if (strcasecmp(argv[i], "OverflowTX") == STR_EQUAL) {
frame.can_id |= CAN_ERR_CRTL; // generate Controller error
frame.data[1] |= CAN_ERR_CRTL_TX_OVERFLOW; // generate TX Overflow suberror
} else if (strcasecmp(argv[i], "WarningRX") == STR_EQUAL) {
frame.can_id |= CAN_ERR_CRTL; // generate Controller error
frame.data[1] |= CAN_ERR_CRTL_RX_WARNING; // generate RX Warning suberror
} else if (strcasecmp(argv[i], "WarningTX") == STR_EQUAL) {
frame.can_id |= CAN_ERR_CRTL; // generate Controller error
frame.data[1] |= CAN_ERR_CRTL_TX_WARNING; // generate TX Warning suberror
} else if (strcasecmp(argv[i], "PassiveRX") == STR_EQUAL) {
frame.can_id |= CAN_ERR_CRTL; // generate Controller error
frame.data[1] |= CAN_ERR_CRTL_RX_PASSIVE; // generate RX Passive suberror
} else if (strcasecmp(argv[i], "PassiveTX") == STR_EQUAL) {
frame.can_id |= CAN_ERR_CRTL; // generate Controller error
frame.data[1] |= CAN_ERR_CRTL_TX_PASSIVE; // generate TX Passive suberror
} else if (strcasecmp(argv[i], "Active") == STR_EQUAL) {
frame.can_id |= CAN_ERR_CRTL; // generate Controller error
frame.data[1] |= CAN_ERR_CRTL_ACTIVE; // generate Active suberror
} else if (strcasecmp(argv[i], "CtrlUnspec") == STR_EQUAL) {
frame.can_id |= CAN_ERR_CRTL; // generate Controller error
frame.data[1] = CAN_ERR_CRTL_UNSPEC; // generate Unspec suberror
}
// error in CAN protocol (type) / data[2]
else if (strcasecmp(argv[i], "SingleBit") == STR_EQUAL) {
frame.can_id |= CAN_ERR_PROT; // generate Protocol Type error
frame.data[2] = CAN_ERR_PROT_BIT; // generate SingleBit suberror
} else if (strcasecmp(argv[i], "FrameFormat") == STR_EQUAL) {
frame.can_id |= CAN_ERR_PROT; // generate Protocol Type error
frame.data[2] = CAN_ERR_PROT_FORM; // generate FrameFormat suberror
} else if (strcasecmp(argv[i], "BitStuffing") == STR_EQUAL) {
frame.can_id |= CAN_ERR_PROT; // generate Protocol Type error
frame.data[2] = CAN_ERR_PROT_STUFF; // generate BitStuffing suberror
} else if (strcasecmp(argv[i], "Bit0") == STR_EQUAL) {
frame.can_id |= CAN_ERR_PROT; // generate Protocol Type error
frame.data[2] = CAN_ERR_PROT_BIT0; // generate Bit0 suberror
} else if (strcasecmp(argv[i], "Bit1") == STR_EQUAL) {
frame.can_id |= CAN_ERR_PROT; // generate Protocol Type error
frame.data[2] = CAN_ERR_PROT_BIT1; // generate Bit1 suberror
} else if (strcasecmp(argv[i], "BusOverload") == STR_EQUAL) {
frame.can_id |= CAN_ERR_PROT; // generate Protocol Type error
frame.data[2] = CAN_ERR_PROT_OVERLOAD; // generate BusOverload suberror
} else if (strcasecmp(argv[i], "ActiveAnnouncement") == STR_EQUAL) {
frame.can_id |= CAN_ERR_PROT; // generate Protocol Type error
frame.data[2] = CAN_ERR_PROT_ACTIVE; // generate ActiveAnnouncement suberror
} else if (strcasecmp(argv[i], "TX") == STR_EQUAL) {
frame.can_id |= CAN_ERR_PROT; // generate Protocol Type error
frame.data[2] = CAN_ERR_PROT_TX; // generate TX suberror
} else if (strcasecmp(argv[i], "ProtUnspec") == STR_EQUAL) {
frame.can_id |= CAN_ERR_PROT; // generate Protocol Type error
frame.data[2] = CAN_ERR_PROT_UNSPEC; // generate Unspec suberror
}
// error in CAN protocol (location) / data[3]
else if (strcasecmp(argv[i], "LocUnspec") == STR_EQUAL) {
if (location_processed)
show_loc_err_and_exit();
frame.can_id |= CAN_ERR_PROT; // generate Protocol Location error
frame.data[3] = CAN_ERR_PROT_LOC_UNSPEC; // generate Unspec suberror
location_processed = true;
} else if (strcasecmp(argv[i], "SOF") == STR_EQUAL) {
if (location_processed)
show_loc_err_and_exit();
frame.can_id |= CAN_ERR_PROT; // generate Protocol Location error
frame.data[3] = CAN_ERR_PROT_LOC_SOF; // generate SOF suberror
location_processed = true;
} else if (strcasecmp(argv[i], "SOF") == STR_EQUAL) {
if (location_processed)
show_loc_err_and_exit();
frame.can_id |= CAN_ERR_PROT; // generate Protocol Location error
frame.data[3] = CAN_ERR_PROT_LOC_SOF; // generate SOF suberror
location_processed = true;
} else if (strcasecmp(argv[i], "ID28_21") == STR_EQUAL) {
if (location_processed)
show_loc_err_and_exit();
frame.can_id |= CAN_ERR_PROT; // generate Protocol Location error
frame.data[3] = CAN_ERR_PROT_LOC_ID28_21; // generate ID28_21 suberror
location_processed = true;
} else if (strcasecmp(argv[i], "ID20_18") == STR_EQUAL) {
if (location_processed)
show_loc_err_and_exit();
frame.can_id |= CAN_ERR_PROT; // generate Protocol Location error
frame.data[3] = CAN_ERR_PROT_LOC_ID20_18; // generate ID20_18 suberror
location_processed = true;
} else if (strcasecmp(argv[i], "SRTR") == STR_EQUAL) {
if (location_processed)
show_loc_err_and_exit();
frame.can_id |= CAN_ERR_PROT; // generate Protocol Location error
frame.data[3] = CAN_ERR_PROT_LOC_SRTR; // generate SRTR suberror
location_processed = true;
} else if (strcasecmp(argv[i], "IDE") == STR_EQUAL) {
if (location_processed)
show_loc_err_and_exit();
frame.can_id |= CAN_ERR_PROT; // generate Protocol Location error
frame.data[3] = CAN_ERR_PROT_LOC_IDE; // generate IDE suberror
location_processed = true;
} else if (strcasecmp(argv[i], "ID17_13") == STR_EQUAL) {
if (location_processed)
show_loc_err_and_exit();
frame.can_id |= CAN_ERR_PROT; // generate Protocol Location error
frame.data[3] = CAN_ERR_PROT_LOC_ID17_13; // generate ID17_13 suberror
location_processed = true;
} else if (strcasecmp(argv[i], "ID12_05") == STR_EQUAL) {
if (location_processed)
show_loc_err_and_exit();
frame.can_id |= CAN_ERR_PROT; // generate Protocol Location error
frame.data[3] = CAN_ERR_PROT_LOC_ID12_05; // generate ID12_05 suberror
location_processed = true;
} else if (strcasecmp(argv[i], "ID04_00") == STR_EQUAL) {
if (location_processed)
show_loc_err_and_exit();
frame.can_id |= CAN_ERR_PROT; // generate Protocol Location error
frame.data[3] = CAN_ERR_PROT_LOC_ID04_00; // generate ID04_00 suberror
location_processed = true;
} else if (strcasecmp(argv[i], "RTR") == STR_EQUAL) {
if (location_processed)
show_loc_err_and_exit();
frame.can_id |= CAN_ERR_PROT; // generate Protocol Location error
frame.data[3] = CAN_ERR_PROT_LOC_RTR; // generate RTR suberror
location_processed = true;
} else if (strcasecmp(argv[i], "RES1") == STR_EQUAL) {
if (location_processed)
show_loc_err_and_exit();
frame.can_id |= CAN_ERR_PROT; // generate Protocol Location error
frame.data[3] = CAN_ERR_PROT_LOC_RES1; // generate RES1 suberror
location_processed = true;
} else if (strcasecmp(argv[i], "RES0") == STR_EQUAL) {
if (location_processed)
show_loc_err_and_exit();
frame.can_id |= CAN_ERR_PROT; // generate Protocol Location error
frame.data[3] = CAN_ERR_PROT_LOC_RES0; // generate RES0 suberror
location_processed = true;
} else if (strcasecmp(argv[i], "DLC") == STR_EQUAL) {
if (location_processed)
show_loc_err_and_exit();
frame.can_id |= CAN_ERR_PROT; // generate Protocol Location error
frame.data[3] = CAN_ERR_PROT_LOC_DLC; // generate DLC suberror
location_processed = true;
} else if (strcasecmp(argv[i], "DATA") == STR_EQUAL) {
if (location_processed)
show_loc_err_and_exit();
frame.can_id |= CAN_ERR_PROT; // generate Protocol Location error
frame.data[3] = CAN_ERR_PROT_LOC_DATA; // generate DATA suberror
location_processed = true;
} else if (strcasecmp(argv[i], "CRC_SEQ") == STR_EQUAL) {
if (location_processed)
show_loc_err_and_exit();
frame.can_id |= CAN_ERR_PROT; // generate Protocol Location error
frame.data[3] = CAN_ERR_PROT_LOC_CRC_SEQ; // generate CRC_SEQ suberror
location_processed = true;
} else if (strcasecmp(argv[i], "CRC_DEL") == STR_EQUAL) {
if (location_processed)
show_loc_err_and_exit();
frame.can_id |= CAN_ERR_PROT; // generate Protocol Location error
frame.data[3] = CAN_ERR_PROT_LOC_CRC_DEL; // generate CRC_DEL suberror
location_processed = true;
} else if (strcasecmp(argv[i], "ACK") == STR_EQUAL) {
if (location_processed)
show_loc_err_and_exit();
frame.can_id |= CAN_ERR_PROT; // generate Protocol Location error
frame.data[3] = CAN_ERR_PROT_LOC_ACK; // generate ACK suberror
location_processed = true;
} else if (strcasecmp(argv[i], "ACK_DEL") == STR_EQUAL) {
if (location_processed)
show_loc_err_and_exit();
frame.can_id |= CAN_ERR_PROT; // generate Protocol Location error
frame.data[3] = CAN_ERR_PROT_LOC_ACK_DEL; // generate ACK_DEL suberror
location_processed = true;
} else if (strcasecmp(argv[i], "EOF") == STR_EQUAL) {
if (location_processed)
show_loc_err_and_exit();
frame.can_id |= CAN_ERR_PROT; // generate Protocol Location error
frame.data[3] = CAN_ERR_PROT_LOC_EOF; // generate EOF suberror
location_processed = true;
} else if (strcasecmp(argv[i], "INTERM") == STR_EQUAL) {
if (location_processed)
show_loc_err_and_exit();
frame.can_id |= CAN_ERR_PROT; // generate Protocol Location error
frame.data[3] = CAN_ERR_PROT_LOC_INTERM; // generate INTERM suberror
location_processed = true;
}
// error status of CAN transceiver / data[4]
else if (strcasecmp(argv[i], "TransUnspec") == STR_EQUAL) {
if (transceiver_processed)
show_transc_err_and_exit();
frame.can_id |= CAN_ERR_TRX; // generate Transceiver error
frame.data[4] = CAN_ERR_TRX_UNSPEC; // generate EOF suberror
location_processed = true;
} else if (strcasecmp(argv[i], "CanHiNoWire") == STR_EQUAL) {
if (transceiver_processed)
show_transc_err_and_exit();
frame.can_id |= CAN_ERR_TRX; // generate Transceiver error
frame.data[4] = CAN_ERR_TRX_CANH_NO_WIRE; // generate CanHiNoWire suberror
location_processed = true;
} else if (strcasecmp(argv[i], "CanHiShortToBAT") == STR_EQUAL) {
if (transceiver_processed)
show_transc_err_and_exit();
frame.can_id |= CAN_ERR_TRX; // generate Transceiver error
frame.data[4] = CAN_ERR_TRX_CANH_SHORT_TO_BAT; // generate CanHiShortToBAT suberror
location_processed = true;
} else if (strcasecmp(argv[i], "CanHiShortToVCC") == STR_EQUAL) {
if (transceiver_processed)
show_transc_err_and_exit();
frame.can_id |= CAN_ERR_TRX; // generate Transceiver error
frame.data[4] = CAN_ERR_TRX_CANH_SHORT_TO_VCC; // generate CanHiShortToVCC suberror
location_processed = true;
} else if (strcasecmp(argv[i], "CanHiShortToGND") == STR_EQUAL) {
if (transceiver_processed)
show_transc_err_and_exit();
frame.can_id |= CAN_ERR_TRX; // generate Transceiver error
frame.data[4] = CAN_ERR_TRX_CANH_SHORT_TO_GND; // generate CanHiShortToGND suberror
location_processed = true;
} else if (strcasecmp(argv[i], "CanLoNoWire") == STR_EQUAL) {
if (transceiver_processed)
show_transc_err_and_exit();
frame.can_id |= CAN_ERR_TRX; // generate Transceiver error
frame.data[4] = CAN_ERR_TRX_CANL_NO_WIRE; // generate CanLoNoWire suberror
location_processed = true;
} else if (strcasecmp(argv[i], "CanLoShortToBAT") == STR_EQUAL) {
if (transceiver_processed)
show_transc_err_and_exit();
frame.can_id |= CAN_ERR_TRX; // generate Transceiver error
frame.data[4] = CAN_ERR_TRX_CANL_SHORT_TO_BAT; // generate CanLoShortToBAT suberror
location_processed = true;
} else if (strcasecmp(argv[i], "CanLoShortToVCC") == STR_EQUAL) {
if (transceiver_processed)
show_transc_err_and_exit();
frame.can_id |= CAN_ERR_TRX; // generate Transceiver error
frame.data[4] = CAN_ERR_TRX_CANL_SHORT_TO_VCC; // generate CanLoShortToVCC suberror
location_processed = true;
} else if (strcasecmp(argv[i], "CanLoShortToGND") == STR_EQUAL) {
if (transceiver_processed)
show_transc_err_and_exit();
frame.can_id |= CAN_ERR_TRX; // generate Transceiver error
frame.data[4] = CAN_ERR_TRX_CANL_SHORT_TO_GND; // generate CanLoShortToGND suberror
location_processed = true;
} else if (strcasecmp(argv[i], "CanLoShortToCanHi") == STR_EQUAL) {
if (transceiver_processed)
show_transc_err_and_exit();
frame.can_id |= CAN_ERR_TRX; // generate Transceiver error
frame.data[4] = CAN_ERR_TRX_CANL_SHORT_TO_CANH; // generate CanLoShortToCanHi suberror
location_processed = true;
}
// LostArBit=29 (Totallength=12)
else if ((strlen(argv[i]) == 12) && // 'LostArBit=29'
(argv[i][9] == '=') && // '='
(argv[i][10] >= '0' && argv[i][10] <= '2') && // valid bits are from 00 to 29 (in decimal)
(argv[i][11] >= '0' && argv[i][11] <= '9')) { // valid bits are from 00 to 29 (in decimal)
unsigned char arb_bit_num = (argv[i][10] - '0') * 10 + argv[i][11] - '0'; // convert decimal bitnumber to byte
argv[i][9] = 0; // terminate string for comparison
if (strcasecmp(argv[i], "LostArBit") == STR_EQUAL) {
if (arbitration_processed)
show_arb_err_and_exit();
frame.can_id |= CAN_ERR_LOSTARB; // generate LostArbitartionBit error
frame.data[0] = arb_bit_num; // bitnumber
arbitration_processed = true;
} else {
argv[i][9] = '='; // undo string termination
show_invalid_option(argv[i]);
}
}
// Data1=F4 (Totallength=8) // since this does not set any error bit, has to be combined with other errors
else if ((strlen(argv[i]) == 8) && // 'Data1=F4'
(argv[i][4] >= '0' && argv[i][4] <= '7') && // valid data bytes are from 0 to 7 (in decimal)
(argv[i][5] == '=') && // '='
((argv[i][6] >= '0' && argv[i][6] <= '9') || (argv[i][6] >= 'A' && argv[i][6] <= 'F')) && // first hexadecimal digit
((argv[i][7] >= '0' && argv[i][7] <= '9') || (argv[i][6] >= 'A' && argv[i][6] <= 'F'))) { // second hexadecimal digit
unsigned char data_byte_value, data_byte_no = 0;
data_byte_no = argv[i][4] - '0'; // convert order number of data byte (Data1 to 1, Data2 to 2...)
data_byte_value = 0;
if (argv[i][6] >= 'A') // convert higher digit hexadecimal char to byte
data_byte_value += (argv[i][6] - 'A' + 10) * 16;
else
data_byte_value += (argv[i][6] - '0') * 16;
if (argv[i][7] >= 'A') // convert lower digit hexadecimal char to byte
data_byte_value += (argv[i][7] - 'A' + 10);
else
data_byte_value += (argv[i][7] - '0');
argv[i][4] = 0; // terminate string for comparison
if (strcasecmp(argv[i], "Data") == STR_EQUAL) {
if (transceiver_processed)
show_transc_err_and_exit();
frame.data[data_byte_no] = data_byte_value; // populate proper data byte
arbitration_processed = true;
} else {
argv[i][4] = data_byte_no + '0'; // undo string termination
show_invalid_option(argv[i]);
}
}
// RxCount=F4 or TxCount=3A (Totallength=10)
else if ((strlen(argv[i]) == 10) && // 'RxCounter=F4' or 'TxCounter=3A'
(argv[i][7] == '=') && // '='
((argv[i][8] >= '0' && argv[i][8] <= '9') || (argv[i][8] >= 'A' && argv[i][8] <= 'F')) && // first hexadecimal digit
((argv[i][9] >= '0' && argv[i][9] <= '9') || (argv[i][9] >= 'A' && argv[i][9] <= 'F'))) { // second hexadecimal digit
unsigned char counter_value = 0;
if (argv[i][8] >= 'A') // convert higher digit hexadecimal char to byte
counter_value += (argv[i][8] - 'A' + 10) * 16;
else
counter_value += (argv[i][8] - '0') * 16;
if (argv[i][9] >= 'A') // convert lower digit hexadecimal char to byte
counter_value += (argv[i][9] - 'A' + 10);
else
counter_value += (argv[i][9] - '0');
argv[i][7] = 0; // terminate string for comparison
if (strcasecmp(argv[i], "TxCount") == STR_EQUAL) {
frame.can_id |= CAN_ERR_CNT; // generate TxCounter error
frame.data[6] = counter_value; // populate proper data byte
} else if (strcasecmp(argv[i], "RxCount") == STR_EQUAL) {
frame.can_id |= CAN_ERR_CNT; // generate RxCounter error
frame.data[7] = counter_value; // populate proper data byte
} else {
argv[i][7] = '='; // undo string termination
show_invalid_option(argv[i]);
}
} else if (strcasecmp(argv[i], "ShowBits") == STR_EQUAL) // DEBUG helper
show_bits = true; // Display frame as bits
else
show_invalid_option(argv[i]);
}
if (show_bits == true) {
printf("CAN ID = ");
print_binary(frame.can_id);
printf("\n");
// printf("frame.can_dlc = %d\n", frame.can_dlc);
printf("CAN Data = ");
for (size_t i = 0; i < frame.can_dlc; i++)
printf("%02X ", frame.data[i]);
printf("\n");
}
// create socket
if ((sock = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
err_exit("Error while opening socket\n");
// set interface name
if (strlen(argv[1]) >= IFNAMSIZ)
err_exit("Name of CAN device '%s' is too long!\n\n", argv[1]);
strcpy(ifr.ifr_name, argv[1]); // can0, vcan0...
if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0)
err_exit("Error setting CAN interface name %s\n", argv[1]);
// bind socket to the CAN interface
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
err_exit("Error in socket bind\n");
// Send CAN error frame
if (write(sock, &frame, sizeof(frame)) < 0)
err_exit("Error writing to socket\n");
else
printf("CAN error frame sent\n");
close(sock);
return 0;
}
+32 -88
View File
@@ -180,7 +180,7 @@ static void print_usage(char *prg)
fprintf(stderr, " -X (generate CAN XL CAN frames)\n"); fprintf(stderr, " -X (generate CAN XL CAN frames)\n");
fprintf(stderr, " -R (generate RTR frames)\n"); fprintf(stderr, " -R (generate RTR frames)\n");
fprintf(stderr, " -8 (allow DLC values greater then 8 for Classic CAN frames)\n"); fprintf(stderr, " -8 (allow DLC values greater then 8 for Classic CAN frames)\n");
fprintf(stderr, " -m (mix CC [-e -R] FD [-f -b -E] XL [-X] on capable devices)\n"); fprintf(stderr, " -m (mix -e -f -b -E -R -X frames)\n");
fprintf(stderr, " -I <mode> (CAN ID generation mode - see below)\n"); fprintf(stderr, " -I <mode> (CAN ID generation mode - see below)\n");
fprintf(stderr, " -L <mode> (CAN data length code (dlc) generation mode - see below)\n"); fprintf(stderr, " -L <mode> (CAN data length code (dlc) generation mode - see below)\n");
fprintf(stderr, " -D <mode> (CAN data (payload) generation mode - see below)\n"); fprintf(stderr, " -D <mode> (CAN data (payload) generation mode - see below)\n");
@@ -299,7 +299,7 @@ static int setsockopt_txtime(int fd)
return 0; return 0;
} }
static int do_send_one(int fd, union cfu *cu, size_t len, int timeout) static int do_send_one(int fd, cu_t *cu, size_t len, int timeout)
{ {
uint8_t control[CMSG_SPACE(sizeof(uint64_t))] = { 0 }; uint8_t control[CMSG_SPACE(sizeof(uint64_t))] = { 0 };
struct iovec iov = { struct iovec iov = {
@@ -339,9 +339,10 @@ resend:
nbytes = sendmsg(fd, &msg, 0); nbytes = sendmsg(fd, &msg, 0);
if (nbytes < 0) { if (nbytes < 0) {
ret = -errno; ret = -errno;
if (ret != -ENOBUFS) if (ret != -ENOBUFS) {
perror("write");
return ret; return ret;
}
if (!ignore_enobufs && !timeout) { if (!ignore_enobufs && !timeout) {
perror("write"); perror("write");
return ret; return ret;
@@ -454,9 +455,6 @@ int main(int argc, char **argv)
unsigned char extended = 0; unsigned char extended = 0;
unsigned char canfd = 0; unsigned char canfd = 0;
unsigned char canxl = 0; unsigned char canxl = 0;
unsigned char mixcc = 1; /* mix default */
unsigned char mixfd = 1; /* mix default */
unsigned char mixxl = 1; /* mix default */
unsigned char brs = 0; unsigned char brs = 0;
unsigned char esi = 0; unsigned char esi = 0;
unsigned char mix = 0; unsigned char mix = 0;
@@ -494,7 +492,7 @@ int main(int argc, char **argv)
struct can_raw_vcid_options vcid_opts = { struct can_raw_vcid_options vcid_opts = {
.flags = CAN_RAW_XL_VCID_TX_PASS, .flags = CAN_RAW_XL_VCID_TX_PASS,
}; };
static union cfu cu; static cu_t cu;
int i; int i;
struct ifreq ifr = { 0 }; struct ifreq ifr = { 0 };
const int enable_canfx = 1; const int enable_canfx = 1;
@@ -576,6 +574,7 @@ int main(int argc, char **argv)
case 'm': case 'm':
mix = 1; mix = 1;
canfd = 1; /* to switch the socket into CAN FD mode */
view |= CANLIB_VIEW_INDENT_SFF; view |= CANLIB_VIEW_INDENT_SFF;
break; break;
@@ -778,32 +777,34 @@ int main(int argc, char **argv)
&loopback, sizeof(loopback)); &loopback, sizeof(loopback));
} }
/* get CAN netdevice MTU for frame type capabilities */ if (canfd || canxl) {
/* check if the frame fits into the CAN netdevice */
if (ioctl(s, SIOCGIFMTU, &ifr) < 0) { if (ioctl(s, SIOCGIFMTU, &ifr) < 0) {
perror("SIOCGIFMTU"); perror("SIOCGIFMTU");
return 1; return 1;
} }
/* check CAN XL support */ if (canfd) {
if (ifr.ifr_mtu < (int)CANXL_MIN_MTU) { /* ensure discrete CAN FD length values 0..8, 12, 16, 20, 24, 32, 64 */
mixxl = 0; cu.fd.len = can_fd_dlc2len(can_fd_len2dlc(cu.fd.len));
if (canxl) { } else {
/* limit fixed CAN XL data length to 64 */
if (cu.fd.len > CANFD_MAX_DLEN)
cu.fd.len = CANFD_MAX_DLEN;
}
if (canxl && (ifr.ifr_mtu < (int)CANXL_MIN_MTU)) {
printf("CAN interface not CAN XL capable - sorry.\n"); printf("CAN interface not CAN XL capable - sorry.\n");
return 1; return 1;
} }
}
/* check CAN FD support */ if (canfd && (ifr.ifr_mtu < (int)CANFD_MTU)) {
if (ifr.ifr_mtu < (int)CANFD_MTU) {
mixfd = 0;
if (canfd) {
printf("CAN interface not CAN FD capable - sorry.\n"); printf("CAN interface not CAN FD capable - sorry.\n");
return 1; return 1;
} }
}
/* enable CAN FD on the socket */ if (ifr.ifr_mtu == (int)CANFD_MTU) {
if (mixfd) {
/* interface is ok - try to switch the socket into CAN FD mode */ /* interface is ok - try to switch the socket into CAN FD mode */
if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES,
&enable_canfx, sizeof(enable_canfx))){ &enable_canfx, sizeof(enable_canfx))){
@@ -812,8 +813,7 @@ int main(int argc, char **argv)
} }
} }
/* enable CAN XL on the socket */ if (ifr.ifr_mtu >= (int)CANXL_MIN_MTU) {
if (mixxl) {
/* interface is ok - try to switch the socket into CAN XL mode */ /* interface is ok - try to switch the socket into CAN XL mode */
if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_XL_FRAMES, if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_XL_FRAMES,
&enable_canfx, sizeof(enable_canfx))){ &enable_canfx, sizeof(enable_canfx))){
@@ -828,16 +828,6 @@ int main(int argc, char **argv)
} }
} }
/* sanitize given values */
if (canfd || canxl) {
if (canfd) {
/* ensure discrete CAN FD length values 0..8, 12, 16, 20, 24, 32, 64 */
cu.fd.len = can_fd_dlc2len(can_fd_len2dlc(cu.fd.len));
} else {
/* limit fixed CAN XL data length to 64 */
if (cu.fd.len > CANFD_MAX_DLEN)
cu.fd.len = CANFD_MAX_DLEN;
}
} else { } else {
/* sanitize Classical CAN 2.0 frame length */ /* sanitize Classical CAN 2.0 frame length */
if (len8_dlc) { if (len8_dlc) {
@@ -997,12 +987,12 @@ int main(int argc, char **argv)
rnd = random(); rnd = random();
if (xl_flags_mode == MODE_RANDOM) { if (xl_flags_mode == MODE_RANDOM) {
cu.xl.flags = rnd & (CANXL_SEC | CANXL_RRS); cu.xl.flags = rnd & CANXL_SEC;
} else if (xl_flags_mode == MODE_FIX) { } else if (xl_flags_mode == MODE_FIX) {
cu.xl.flags = xl_flags; cu.xl.flags = xl_flags;
} else if (xl_flags_mode == MODE_INCREMENT) { } else if (xl_flags_mode == MODE_INCREMENT) {
xl_flags++; xl_flags ^= CANXL_SEC;
cu.xl.flags = (xl_flags & (CANXL_SEC | CANXL_RRS)); cu.xl.flags = (xl_flags & CANXL_SEC);
} }
/* mark CAN XL frame */ /* mark CAN XL frame */
@@ -1050,31 +1040,8 @@ int main(int argc, char **argv)
} }
ret = do_send_one(s, &cu, mtu, polltimeout); ret = do_send_one(s, &cu, mtu, polltimeout);
if ((ret == -EINVAL) && mix) { if (ret)
/* mix mode: disable unsupported CAN frame type */
switch (mtu) {
case CAN_MTU:
mixcc = 0;
break;
case CANFD_MTU:
mixfd = 0;
break;
case CANXL_MTU:
mixxl = 0;
break;
default:
printf ("mix mode: unknown MTU");
return 1; return 1;
}
if (!mixcc && !mixfd && !mixxl) {
printf ("mix mode: no valid CAN frame types\n");
return 1;
}
} else if (ret) {
/* other error than -ENOBUFS and -EINVAL */
perror("write");
return 1;
}
if (burst_sent_count >= burst_count) if (burst_sent_count >= burst_count)
burst_sent_count = 0; burst_sent_count = 0;
@@ -1115,41 +1082,18 @@ int main(int argc, char **argv)
} }
if (mix) { if (mix) {
canfd = 0;
canxl = 0;
i = random(); i = random();
extended = i & 1; extended = i & 1;
if (mixfd) {
canfd = i & 2; canfd = i & 2;
if (canfd) { if (canfd) {
brs = i & 4; brs = i & 4;
esi = i & 8; esi = i & 8;
} }
} /* generate CAN XL traffic if the interface is capable */
if (mixxl) { if (ifr.ifr_mtu >= (int)CANXL_MIN_MTU)
if (mixfd) canxl = ((i & 96) == 96);
canxl = ((i & 96) == 96); /* 1/4 */
else rtr_frame = ((i & 24) == 24); /* reduce RTR frames to 1/4 */
canxl = ((i & 32) == 32); /* 1/2 */
}
if (mixcc) {
rtr_frame = ((i & 24) == 24); /* reduce RTR to 1/4 */
} else {
/* no CC frames allowed - CAN XL-only mode? */
if (!canxl && !canfd) {
/* force XL or FD frames */
if (mixxl)
canxl = 1;
else if (mixfd) {
canfd = 1;
brs = i & 4;
esi = i & 8;
} else {
printf ("mix mode: no valid CAN frame types\n");
return 1;
}
}
}
} }
} }
+4 -26
View File
@@ -177,8 +177,7 @@ int main(int argc, char **argv)
sigset_t sigset; sigset_t sigset;
fd_set rdfs; fd_set rdfs;
int s[MAXDEV]; int s[MAXDEV];
int socki; int socki, accsocket;
int accsocket = -1;
canid_t mask[MAXDEV] = {0}; canid_t mask[MAXDEV] = {0};
canid_t value[MAXDEV] = {0}; canid_t value[MAXDEV] = {0};
int inv_filter[MAXDEV] = {0}; int inv_filter[MAXDEV] = {0};
@@ -192,7 +191,7 @@ int main(int argc, char **argv)
.rx_vcid_mask = 0, .rx_vcid_mask = 0,
}; };
struct can_filter rfilter; struct can_filter rfilter;
static union cfu cu; /* union for CAN CC/FD/XL frames */ static cu_t cu; /* union for CAN CC/FD/XL frames */
const int canfx_on = 1; const int canfx_on = 1;
int nbytes, i, j; int nbytes, i, j;
struct ifreq ifr; struct ifreq ifr;
@@ -287,7 +286,7 @@ int main(int argc, char **argv)
inaddr.sin_addr.s_addr = htonl(INADDR_ANY); inaddr.sin_addr.s_addr = htonl(INADDR_ANY);
inaddr.sin_port = htons(port); inaddr.sin_port = htons(port);
while(running && bind(socki, (struct sockaddr*)&inaddr, sizeof(inaddr)) < 0) { while(bind(socki, (struct sockaddr*)&inaddr, sizeof(inaddr)) < 0) {
struct timespec f = { struct timespec f = {
.tv_nsec = 100 * 1000 * 1000, .tv_nsec = 100 * 1000 * 1000,
}; };
@@ -296,28 +295,18 @@ int main(int argc, char **argv)
nanosleep(&f, NULL); nanosleep(&f, NULL);
} }
/*
* Check if loop exited due to signal (during nanosleep) rather than
* successful bind.
*/
if (!running) {
close(socki);
return 128 + signal_num;
}
if (listen(socki, 3) != 0) { if (listen(socki, 3) != 0) {
perror("listen"); perror("listen");
exit(1); exit(1);
} }
while(running) { while(1) {
accsocket = accept(socki, (struct sockaddr*)&clientaddr, &sin_size); accsocket = accept(socki, (struct sockaddr*)&clientaddr, &sin_size);
if (accsocket > 0) { if (accsocket > 0) {
//printf("accepted\n"); //printf("accepted\n");
if (!fork()) if (!fork())
break; break;
close(accsocket); close(accsocket);
accsocket = -1;
} }
else if (errno != EINTR) { else if (errno != EINTR) {
perror("accept"); perror("accept");
@@ -325,17 +314,6 @@ int main(int argc, char **argv)
} }
} }
/*
* Check if loop exited due to signal (accept returned EINTR) rather
* than successful fork
*/
if (!running) {
if (accsocket > 0)
close(accsocket);
close(socki);
return 128 + signal_num;
}
for (i=0; i<currmax; i++) { for (i=0; i<currmax; i++) {
pr_debug("open %d '%s' m%08X v%08X i%d e%d.\n", pr_debug("open %d '%s' m%08X v%08X i%d e%d.\n",
+11 -23
View File
@@ -68,7 +68,7 @@
#endif #endif
#define DEVSZ 22 /* IFNAMSZ + 6 */ #define DEVSZ 22 /* IFNAMSZ + 6 */
#define TIMESZ sizeof("(1345212884.318850123) ") #define TIMESZ sizeof("(1345212884.318850) ")
#define BUFSZ (TIMESZ + DEVSZ + AFRSZ) #define BUFSZ (TIMESZ + DEVSZ + AFRSZ)
/* adapt sscanf() functions below on error */ /* adapt sscanf() functions below on error */
@@ -261,7 +261,7 @@ int main(int argc, char **argv)
struct can_raw_vcid_options vcid_opts = { struct can_raw_vcid_options vcid_opts = {
.flags = CAN_RAW_XL_VCID_TX_PASS, .flags = CAN_RAW_XL_VCID_TX_PASS,
}; };
static union cfu cu; static cu_t cu;
static struct timeval today_tv, log_tv, last_log_tv, diff_tv; static struct timeval today_tv, log_tv, last_log_tv, diff_tv;
struct timespec sleep_ts; struct timespec sleep_ts;
int s; /* CAN_RAW socket */ int s; /* CAN_RAW socket */
@@ -452,20 +452,14 @@ int main(int argc, char **argv)
return 1; return 1;
} }
log_tv.tv_sec = sec; log_tv.tv_sec = sec;
log_tv.tv_usec = usec;
/* /*
* ensure the fractions of seconds are 6 or 9 decimal places long to catch * ensure the fractions of seconds are 6 decimal places long to catch
* 3rd party or handcrafted logfiles that treat the timestamp as float * 3rd party or handcrafted logfiles that treat the timestamp as float
*/ */
switch (strchr(buf, ')') - strchr(buf, '.')) { if (strchr(buf, ')') - strchr(buf, '.') != 7) {
case 7: //6 fprintf(stderr, "timestamp format in logfile requires 6 decimal places\n");
log_tv.tv_usec = usec;
break;
case 10: //9
log_tv.tv_usec = usec / 1000;
break;
default:
fprintf(stderr, "timestamp format in logfile requires 6 or 9 decimal places\n");
return 1; return 1;
} }
@@ -547,25 +541,19 @@ int main(int argc, char **argv)
break; break;
} }
if (sscanf(buf, "(%llu.%llu) %21s %6299s", &sec, &usec, device, afrbuf) != 4) { if (sscanf(buf, "(%llu.%llu) %s %s", &sec, &usec, device, afrbuf) != 4) {
fprintf(stderr, "incorrect line format in logfile\n"); fprintf(stderr, "incorrect line format in logfile\n");
return 1; return 1;
} }
log_tv.tv_sec = sec; log_tv.tv_sec = sec;
log_tv.tv_usec = usec;
/* /*
* ensure the fractions of seconds are 6 or 9 decimal places long to catch * ensure the fractions of seconds are 6 decimal places long to catch
* 3rd party or handcrafted logfiles that treat the timestamp as float * 3rd party or handcrafted logfiles that treat the timestamp as float
*/ */
switch (strchr(buf, ')') - strchr(buf, '.')) { if (strchr(buf, ')') - strchr(buf, '.') != 7) {
case 7: //6 fprintf(stderr, "timestamp format in logfile requires 6 decimal places\n");
log_tv.tv_usec = usec;
break;
case 10: //9
log_tv.tv_usec = usec / 1000;
break;
default:
fprintf(stderr, "timestamp format in logfile requires 6 or 9 decimal places\n");
return 1; return 1;
} }
+3 -7
View File
@@ -80,10 +80,7 @@ static void print_usage(char *prg)
"_{dlc}:\n" "_{dlc}:\n"
" an optional 9..F data length code value when payload length is 8\n" " an optional 9..F data length code value when payload length is 8\n"
"<flags>:\n" "<flags>:\n"
" a single ASCII Hex value (0 .. F) which defines canfd_frame.flags:\n" " a single ASCII Hex value (0 .. F) which defines canfd_frame.flags\n"
" %x CANFD_BRS\n"
" %x CANFD_ESI\n"
" %x CANFD_FDF\n"
"\n" "\n"
"<vcid>:\n" "<vcid>:\n"
" 2 hex chars - virtual CAN network identifier (00 .. FF)\n" " 2 hex chars - virtual CAN network identifier (00 .. FF)\n"
@@ -103,8 +100,7 @@ static void print_usage(char *prg)
" 1F334455#1122334455667788_B / 123#R / 00000123#R3 / 333#R8_E /\n" " 1F334455#1122334455667788_B / 123#R / 00000123#R3 / 333#R8_E /\n"
" 45123#81:00:12345678#11223344.556677 / 00242#81:07:40000123#112233\n" " 45123#81:00:12345678#11223344.556677 / 00242#81:07:40000123#112233\n"
"\n", "\n",
prg, prg, prg, prg);
CANFD_BRS, CANFD_ESI, CANFD_FDF);
} }
int main(int argc, char **argv) int main(int argc, char **argv)
@@ -117,7 +113,7 @@ int main(int argc, char **argv)
struct can_raw_vcid_options vcid_opts = { struct can_raw_vcid_options vcid_opts = {
.flags = CAN_RAW_XL_VCID_TX_PASS, .flags = CAN_RAW_XL_VCID_TX_PASS,
}; };
static union cfu cu; static cu_t cu;
struct ifreq ifr; struct ifreq ifr;
/* check command line options */ /* check command line options */
+1 -1
View File
@@ -1077,7 +1077,7 @@ int isobusfs_cli_interactive(struct isobusfs_priv *priv)
} }
} }
pr_int("unknown command\n"); pr_int("unknown comand\n");
isobusfs_cli_promt(priv); isobusfs_cli_promt(priv);
} else { } else {
if (errno != EAGAIN && errno != EWOULDBLOCK) if (errno != EAGAIN && errno != EWOULDBLOCK)
+1 -1
View File
@@ -211,7 +211,7 @@ static struct isobusfs_cli_test_dir_path test_dir_patterns[] = {
{ "~tilde_dir", true }, { "~tilde_dir", true },
/* expected result \\vol1\dir1\~\ */ /* expected result \\vol1\dir1\~\ */
{ "\\\\vol1\\dir1\\~", true }, { "\\\\vol1\\dir1\\~", true },
/* expected result \\vol1\~\ not clear if it is manufacture specific dir */ /* expected result \\vol1\~\ not clear if it is manufacture speficic dir */
{ "\\~\\", true }, { "\\~\\", true },
/* expected result \\~\ */ /* expected result \\~\ */
{ "\\\\~\\", false }, { "\\\\~\\", false },
+1 -1
View File
@@ -611,7 +611,7 @@ int isobusfs_cmn_connect_socket(int sock, struct sockaddr_can *addr)
} }
/* FIXME: linger is currently not supported by the kernel J1939 stack /* FIXME: linger is currently not supported by the kernel J1939 stack
* but it would be nice to have it. Especially if we won't to stop sending * but it would be nice to have it. Especially if we wont to stop sending
* messages on a socket when the connection is lost. * messages on a socket when the connection is lost.
*/ */
int isobusfs_cmn_set_linger(int sock) int isobusfs_cmn_set_linger(int sock)
+1 -1
View File
@@ -23,7 +23,7 @@ int isobusfs_cmn_dh_validate_dir_path(const char *path, bool writable)
ret = access(path, mode); ret = access(path, mode);
if (ret == -1) { if (ret == -1) {
ret = -errno; ret = -errno;
pr_err("failed to access path %s, for read %s. %s", path, pr_err("failed to acces path %s, for read %s. %s", path,
writable ? "and write" : "", strerror(ret)); writable ? "and write" : "", strerror(ret));
return ret; return ret;
} }
+3 -3
View File
@@ -70,7 +70,7 @@ static int isobusfs_srv_rx_fs(struct isobusfs_srv_priv *priv,
cg); cg);
/* ISO 11783-13:2021 - Annex C.1.1 Overview: /* ISO 11783-13:2021 - Annex C.1.1 Overview:
* If a client sends a command, which is not defined within this * If a client sends a command, which is not defined withing this
* documentation, the file server shall respond with a * documentation, the file server shall respond with a
* NACK (ISO 11783-3:2018 Chapter 5.4.5) * NACK (ISO 11783-3:2018 Chapter 5.4.5)
*/ */
@@ -279,7 +279,7 @@ static int isobusfs_srv_sock_fss_prepare(struct isobusfs_srv_priv *priv)
return ret; return ret;
/* keep address and name and overwrite PGN */ /* keep address and name and overwrite PGN */
/* TODO: actually, this is PGN input filter. Should we use different /* TOOD: actually, this is PGN input filter. Should we use different
* PGN? * PGN?
*/ */
addr.can_addr.j1939.pgn = ISOBUSFS_PGN_CL_TO_FS; addr.can_addr.j1939.pgn = ISOBUSFS_PGN_CL_TO_FS;
@@ -720,7 +720,7 @@ static int isobusfs_srv_parse_args(struct isobusfs_srv_priv *priv, int argc,
} }
if (!local_name_set) if (!local_name_set)
pr_warn("local name is not set. Won't be able to generate proper manufacturer-specific directory name. Falling mack to MCMC0000"); pr_warn("local name is not set. Wont be able to generate proper manufacturer-specific directory name. Falling mack to MCMC0000");
isobusfs_srv_generate_mfs_dir_name(priv); isobusfs_srv_generate_mfs_dir_name(priv);
pr_debug("Server configuration:"); pr_debug("Server configuration:");
+3 -3
View File
@@ -662,8 +662,8 @@ static int isobusfs_srv_dh_ccd_res(struct isobusfs_srv_priv *priv,
int ret; int ret;
/* /*
* We assume, the relative path stored in res->name is not longer * We assime, the relative path stored in res->name is not longer
* than absolute path * than absolue path
*/ */
if (req->name_len > ISOBUSFS_SRV_MAX_PATH_LEN) { if (req->name_len > ISOBUSFS_SRV_MAX_PATH_LEN) {
pr_warn("path too long"); pr_warn("path too long");
@@ -697,7 +697,7 @@ static int isobusfs_srv_dh_ccd_res(struct isobusfs_srv_priv *priv,
process_error: process_error:
if (ret < 0) { if (ret < 0) {
/* linux_error_to_isobusfs_error() can't distinguish between /* linux_error_to_isobusfs_error() can't distinguish between
* -EINVAL for SRC and DST, so we have to do it manually. * -EINVAL vor SRC and DST, so we have to do it manually.
*/ */
if (ret == -EINVAL) if (ret == -EINVAL)
error_code = ISOBUSFS_ERR_INVALID_DST_NAME; error_code = ISOBUSFS_ERR_INVALID_DST_NAME;
+1 -1
View File
@@ -686,7 +686,7 @@ send_response:
goto free_res; goto free_res;
} }
pr_debug("> tx: Read File Response. Error code: %d (%s), read size: %d", pr_debug("> tx: Read File Response. Error code: %d (%s), readed size: %d",
error_code, isobusfs_error_to_str(error_code), readed_size); error_code, isobusfs_error_to_str(error_code), readed_size);
free_res: free_res:
-6
View File
@@ -41,7 +41,6 @@ static void gmtime_to_j1939_pgn_65254_td(struct j1939_time_date_packet *tdp)
utc_tm = gmtime_r(&now, &utc_tm_buf); utc_tm = gmtime_r(&now, &utc_tm_buf);
local_tm = localtime_r(&now, &local_tm_buf); local_tm = localtime_r(&now, &local_tm_buf);
if (local_tm) {
/* Calculate the offsets */ /* Calculate the offsets */
hour_offset = local_tm->tm_hour - utc_tm->tm_hour; hour_offset = local_tm->tm_hour - utc_tm->tm_hour;
minute_offset = local_tm->tm_min - utc_tm->tm_min; minute_offset = local_tm->tm_min - utc_tm->tm_min;
@@ -53,11 +52,6 @@ static void gmtime_to_j1939_pgn_65254_td(struct j1939_time_date_packet *tdp)
else else
hour_offset -= 24; /* before midnight */ hour_offset -= 24; /* before midnight */
} }
} else {
/* The local time offsets cannot be determined at the moment */
hour_offset = 0xF9;
minute_offset = 0xFF;
}
/* /*
* Seconds (spn959): * Seconds (spn959):
@@ -51,7 +51,7 @@ struct j1939_vp_err_msg {
#define J1939_VP1_PRIO_DEFAULT 6 #define J1939_VP1_PRIO_DEFAULT 6
#define J1939_VP1_MAX_TRANSFER_LENGH \ #define J1939_VP1_MAX_TRANSFER_LENGH \
sizeof(struct j1939_vp1_packet) sizeof(struct j1939_vp1_packet)
#define J1939_VP1_REPETITION_RATE_MS 1000 #define J1939_VP1_REPETITION_RATE_MS 5000
#define J1939_VP1_JITTER_MS 500 #define J1939_VP1_JITTER_MS 500
/** /**
@@ -63,8 +63,8 @@ struct j1939_vp_err_msg {
* - Data Length: 4 bytes * - Data Length: 4 bytes
* - Resolution: 10^-7 deg/bit * - Resolution: 10^-7 deg/bit
* - Offset: -210 degrees * - Offset: -210 degrees
* - Range: -210 to +211.10081215 degrees * - Range: -210 to +211.1008122 degrees
* - Operating Range: -210 degrees (SOUTH) to +211.1081215 degrees * - Operating Range: -210 degrees (SOUTH) to +211.108122 degrees
* (NORTH) * (NORTH)
* *
* @longitude: Raw longitude position of the vehicle * @longitude: Raw longitude position of the vehicle
@@ -72,8 +72,8 @@ struct j1939_vp_err_msg {
* - Data Length: 4 bytes * - Data Length: 4 bytes
* - Resolution: 10^-7 deg/bit * - Resolution: 10^-7 deg/bit
* - Offset: -210 degrees * - Offset: -210 degrees
* - Range: -210 to +211.10081215 degrees * - Range: -210 to +211.1008122 degrees
* - Operating Range: -210 degrees (WEST) to +211.1081215 degrees * - Operating Range: -210 degrees (WEST) to +211.108122 degrees
* (EAST) * (EAST)
* *
* This structure defines each component of the Vehicle Position as described in * This structure defines each component of the Vehicle Position as described in
@@ -142,35 +142,32 @@ j1939_vp1_set_longitude(struct j1939_vp1_packet *packet, int32_t longitude)
/** /**
* struct j1939_vp2_packet - Represents the PGN 64502 Vehicle * struct j1939_vp2_packet - Represents the PGN 64502 Vehicle
* Position 2 packet * Position 2 packet
* FIXME: current packet layout is guessed based on limited information:
* https://www.isobus.net/isobus/pGNAndSPN/10801?type=PGN
* *
* @total_satellites: Total number of satellites in view * @total_satellites: Total number of satellites in view
* - SPN: 8128 * - SPN: 8128
* - Data Length: 1 byte * - Data Length: 1 byte
* - Range: 0 to 250
* *
* @hdop: Horizontal dilution of precision * @hdop: Horizontal dilution of precision
* - SPN: 8129 * - SPN: 8129
* - Data Length: 1 byte * - Data Length: 1 byte
* - Resolution: 0.1 * - Resolution: 0.1
* - Range: 0.0 to 25.0
* *
* @vdop: Vertical dilution of precision * @vdop: Vertical dilution of precision
* - SPN: 8130 * - SPN: 8130
* - Data Length: 1 byte * - Data Length: 1 byte
* - Resolution: 0.1 * - Resolution: 0.1
* - Range: 0.0 to 25.0
* *
* @pdop: Position dilution of precision * @pdop: Position dilution of precision
* - SPN: 8131 * - SPN: 8131
* - Data Length: 1 byte * - Data Length: 1 byte
* - Resolution: 0.1 * - Resolution: 0.1
* - Range: 0.0 to 25.0
* *
* @tdop: Time dilution of precision * @tdop: Time dilution of precision
* - SPN: 8132 * - SPN: 8132
* - Data Length: 1 byte * - Data Length: 1 byte
* - Resolution: 0.1 * - Resolution: 0.1
* - Range: 0.0 to 25.0
* *
* This structure defines each component of the Vehicle Position 2 as described * This structure defines each component of the Vehicle Position 2 as described
* in PGN 64502. * in PGN 64502.
@@ -181,9 +178,6 @@ struct j1939_vp2_packet {
uint8_t vdop; /* SPN 8130 */ uint8_t vdop; /* SPN 8130 */
uint8_t pdop; /* SPN 8131 */ uint8_t pdop; /* SPN 8131 */
uint8_t tdop; /* SPN 8132 */ uint8_t tdop; /* SPN 8132 */
uint8_t unused5; /* Always 0xFF */
uint8_t unused6; /* Always 0xFF */
uint8_t unused7; /* Always 0xFF */
} __attribute__((__packed__)); } __attribute__((__packed__));
/** /**
@@ -270,12 +270,6 @@ static int j1939_vp2_get_data(struct j1939_vp_srv_priv *priv,
j1939_vp2_set_pdop(vp2p, pdop); j1939_vp2_set_pdop(vp2p, pdop);
j1939_vp2_set_tdop(vp2p, tdop); j1939_vp2_set_tdop(vp2p, tdop);
/* This PG's last 3 bytes are not assigned and hence must be set
* to 0xFF as per J1939-71, section 5.2 */
vp2p->unused5 = 0xFF;
vp2p->unused6 = 0xFF;
vp2p->unused7 = 0xFF;
return 0; return 0;
} }
+16 -23
View File
@@ -83,8 +83,8 @@ static inline void _put_id(char *buf, int end_offset, canid_t id)
/* CAN DLC to real data length conversion helpers */ /* CAN DLC to real data length conversion helpers */
static const unsigned char dlc2len[] = { static const unsigned char dlc2len[] = {0, 1, 2, 3, 4, 5, 6, 7,
0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64}; 8, 12, 16, 20, 24, 32, 48, 64};
/* get data length from raw data length code (DLC) */ /* get data length from raw data length code (DLC) */
unsigned char can_fd_dlc2len(unsigned char dlc) unsigned char can_fd_dlc2len(unsigned char dlc)
@@ -92,8 +92,7 @@ unsigned char can_fd_dlc2len(unsigned char dlc)
return dlc2len[dlc & 0x0F]; return dlc2len[dlc & 0x0F];
} }
static const unsigned char len2dlc[] = { static const unsigned char len2dlc[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, /* 0 - 8 */
0, 1, 2, 3, 4, 5, 6, 7, 8, /* 0 - 8 */
9, 9, 9, 9, /* 9 - 12 */ 9, 9, 9, 9, /* 9 - 12 */
10, 10, 10, 10, /* 13 - 16 */ 10, 10, 10, 10, /* 13 - 16 */
11, 11, 11, 11, /* 17 - 20 */ 11, 11, 11, 11, /* 17 - 20 */
@@ -155,7 +154,7 @@ int hexstring2data(char *arg, unsigned char *data, int maxdlen)
return 0; return 0;
} }
int parse_canframe(char *cs, union cfu *cu) int parse_canframe(char *cs, cu_t *cu)
{ {
/* documentation see lib.h */ /* documentation see lib.h */
@@ -170,23 +169,21 @@ int parse_canframe(char *cs, union cfu *cu)
memset(cu, 0, sizeof(*cu)); /* init CAN CC/FD/XL frame, e.g. LEN = 0 */ memset(cu, 0, sizeof(*cu)); /* init CAN CC/FD/XL frame, e.g. LEN = 0 */
if (len >= 4 && cs[3] == CANID_DELIM) { /* 3 digits SFF CAN ID */ if (len < 4)
return 0;
idx = 4; /* start of frame data */ if (cs[3] == CANID_DELIM) { /* 3 digits SFF */
/* get 3 digits SFF CAN ID value */ idx = 4;
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
if ((tmp = asc2nibble(cs[i])) > 0x0F) if ((tmp = asc2nibble(cs[i])) > 0x0F)
return 0; return 0;
cu->cc.can_id |= tmp << (2 - i) * 4; cu->cc.can_id |= tmp << (2 - i) * 4;
} }
} else if (len >= 21 && cs[5] == CANID_DELIM && cs[20] == CANID_DELIM) { } else if (cs[5] == CANID_DELIM) { /* 5 digits CAN XL VCID/PRIO*/
/* 5 digits CAN XL VCID/PRIO - but also check for 2nd '#' here */
idx = 6; /* start of CAN XL frame extra content (AF, SDT, etc) */ idx = 6;
/* get 5 digits CAN XL VCID/PRIO */
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++) {
if ((tmp = asc2nibble(cs[i])) > 0x0F) if ((tmp = asc2nibble(cs[i])) > 0x0F)
return 0; return 0;
@@ -198,11 +195,9 @@ int parse_canframe(char *cs, union cfu *cu)
cu->xl.prio &= CANXL_PRIO_MASK; cu->xl.prio &= CANXL_PRIO_MASK;
cu->xl.prio |= tmp; cu->xl.prio |= tmp;
} else if (len >= 9 && cs[8] == CANID_DELIM) { /* 8 digits EFF CAN ID */ } else if (cs[8] == CANID_DELIM) { /* 8 digits EFF */
idx = 9; /* start of frame data */ idx = 9;
/* get 8 digits EFF CAN ID value */
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
if ((tmp = asc2nibble(cs[i])) > 0x0F) if ((tmp = asc2nibble(cs[i])) > 0x0F)
return 0; return 0;
@@ -243,12 +238,11 @@ int parse_canframe(char *cs, union cfu *cu)
cu->fd.flags |= CANFD_FDF; /* dual-use */ cu->fd.flags |= CANFD_FDF; /* dual-use */
idx += 2; idx += 2;
} else if (idx == 6) { /* CAN XL frame extra content '#80:00:11223344#' */ } else if (cs[idx + 14] == CANID_DELIM) { /* CAN XL frame '#80:00:11223344#' */
maxdlen = CANXL_MAX_DLEN; maxdlen = CANXL_MAX_DLEN;
mtu = CANXL_MTU; mtu = CANXL_MTU;
data = cu->xl.data; /* overwrite pointer to CAN XL data */ data = cu->xl.data; /* fill CAN XL data */
/* get CAN XL frame extra content */
if ((cs[idx + 2] != XL_HDR_DELIM) || (cs[idx + 5] != XL_HDR_DELIM)) if ((cs[idx + 2] != XL_HDR_DELIM) || (cs[idx + 5] != XL_HDR_DELIM))
return 0; return 0;
@@ -282,7 +276,6 @@ int parse_canframe(char *cs, union cfu *cu)
idx++; /* skip CANID_DELIM */ idx++; /* skip CANID_DELIM */
} }
/* copy CAN frame data content */
for (i = 0, dlen = 0; i < maxdlen; i++) { for (i = 0, dlen = 0; i < maxdlen; i++) {
if (cs[idx] == DATA_SEPERATOR) /* skip (optional) separator */ if (cs[idx] == DATA_SEPERATOR) /* skip (optional) separator */
idx++; idx++;
@@ -315,7 +308,7 @@ int parse_canframe(char *cs, union cfu *cu)
return mtu; return mtu;
} }
int snprintf_canframe(char *buf, size_t size, union cfu *cu, int sep) int snprintf_canframe(char *buf, size_t size, cu_t *cu, int sep)
{ {
/* documentation see lib.h */ /* documentation see lib.h */
@@ -439,7 +432,7 @@ int snprintf_canframe(char *buf, size_t size, union cfu *cu, int sep)
return offset; return offset;
} }
int snprintf_long_canframe(char *buf, size_t size, union cfu *cu, int view) int snprintf_long_canframe(char *buf, size_t size, cu_t *cu, int view)
{ {
/* documentation see lib.h */ /* documentation see lib.h */
+5 -7
View File
@@ -49,8 +49,6 @@
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <linux/can.h>
#ifdef DEBUG #ifdef DEBUG
#define pr_debug(fmt, args...) printf(fmt, ##args) #define pr_debug(fmt, args...) printf(fmt, ##args)
#else #else
@@ -59,11 +57,11 @@ static inline int pr_debug(const char* fmt, ...) {return 0;}
#endif #endif
/* CAN CC/FD/XL frame union */ /* CAN CC/FD/XL frame union */
union cfu { typedef union {
struct can_frame cc; struct can_frame cc;
struct canfd_frame fd; struct canfd_frame fd;
struct canxl_frame xl; struct canxl_frame xl;
}; } cu_t;
/* /*
* The buffer size for ASCII CAN frame string representations * The buffer size for ASCII CAN frame string representations
@@ -110,7 +108,7 @@ int hexstring2data(char *arg, unsigned char *data, int maxdlen);
* *
*/ */
int parse_canframe(char *cs, union cfu *cu); int parse_canframe(char *cs, cu_t *cu);
/* /*
* Transfers a valid ASCII string describing a CAN frame into the CAN union * Transfers a valid ASCII string describing a CAN frame into the CAN union
* containing CAN CC/FD/XL structs. * containing CAN CC/FD/XL structs.
@@ -180,7 +178,7 @@ int parse_canframe(char *cs, union cfu *cu);
* - CAN FD frames do not have a RTR bit * - CAN FD frames do not have a RTR bit
*/ */
int snprintf_canframe(char *buf, size_t size, union cfu *cu, int sep); int snprintf_canframe(char *buf, size_t size, cu_t *cu, int sep);
/* /*
* Creates a CAN frame hexadecimal output in compact format. * Creates a CAN frame hexadecimal output in compact format.
* The CAN data[] is separated by '.' when sep != 0. * The CAN data[] is separated by '.' when sep != 0.
@@ -213,7 +211,7 @@ int snprintf_canframe(char *buf, size_t size, union cfu *cu, int sep);
#define SWAP_DELIMITER '`' #define SWAP_DELIMITER '`'
int snprintf_long_canframe(char *buf, size_t size, union cfu *cu, int view); int snprintf_long_canframe(char *buf, size_t size, cu_t *cu, int view);
/* /*
* Creates a CAN frame hexadecimal output in user readable format. * Creates a CAN frame hexadecimal output in user readable format.
* *
+3 -18
View File
@@ -183,7 +183,7 @@ static void canfd_asc(struct canfd_frame *cf, int devno, int mtu,
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(union cfu *cu, int devno, int mtu, static void canxl_asc(cu_t *cu, int devno, int mtu,
char *extra_info, FILE *outfile) char *extra_info, FILE *outfile)
{ {
char id[10]; char id[10];
@@ -296,7 +296,7 @@ static void canxl_asc(union cfu *cu, int devno, int mtu,
#define DEVSZ 22 #define DEVSZ 22
#define EXTRASZ 20 #define EXTRASZ 20
#define TIMESZ sizeof("(1345212884.318850123) ") #define TIMESZ sizeof("(1345212884.318850) ")
#define BUFSZ (DEVSZ + AFRSZ + EXTRASZ + TIMESZ) #define BUFSZ (DEVSZ + AFRSZ + EXTRASZ + TIMESZ)
/* adapt sscanf() functions below on error */ /* adapt sscanf() functions below on error */
@@ -314,7 +314,7 @@ int main(int argc, char **argv)
{ {
static char buf[BUFSZ], device[DEVSZ], afrbuf[AFRSZ], extra_info[EXTRASZ]; static char buf[BUFSZ], device[DEVSZ], afrbuf[AFRSZ], extra_info[EXTRASZ];
static union cfu cu; static cu_t cu;
static struct timeval tv, start_tv; static struct timeval tv, start_tv;
FILE *infile = stdin; FILE *infile = stdin;
FILE *outfile = stdout; FILE *outfile = stdout;
@@ -407,22 +407,7 @@ int main(int argc, char **argv)
} }
} }
tv.tv_sec = sec; tv.tv_sec = sec;
/*
* ensure the fractions of seconds are 6 or 9 decimal places long to catch
* 3rd party or handcrafted logfiles that treat the timestamp as float
*/
switch (strchr(buf, ')') - strchr(buf, '.')) {
case 7: //6
tv.tv_usec = usec; tv.tv_usec = usec;
break;
case 10: //9
tv.tv_usec = usec / 1000;
break;
default:
fprintf(stderr, "timestamp format in logfile requires 6 or 9 decimal places\n");
return 1;
}
if (print_banner) { /* print banner */ if (print_banner) { /* print banner */
print_banner = 0; print_banner = 0;
+4 -4
View File
@@ -51,7 +51,7 @@
#include "lib.h" #include "lib.h"
#define DEVSZ 22 #define DEVSZ 22
#define TIMESZ 25 /* sizeof("(1345212884.318850123) ") */ #define TIMESZ 22 /* sizeof("(1345212884.318850) ") */
#define BUFSZ (DEVSZ + AFRSZ + TIMESZ) #define BUFSZ (DEVSZ + AFRSZ + TIMESZ)
/* adapt sscanf() functions below on error */ /* adapt sscanf() functions below on error */
@@ -61,14 +61,14 @@
#if (DEVSZ != 22) #if (DEVSZ != 22)
#error "DEVSZ value does not fit sscanf restrictions!" #error "DEVSZ value does not fit sscanf restrictions!"
#endif #endif
#if (TIMESZ != 25) #if (TIMESZ != 22)
#error "TIMESZ value does not fit sscanf restrictions!" #error "TIMESZ value does not fit sscanf restrictions!"
#endif #endif
int main(void) int main(void)
{ {
static char buf[BUFSZ], timestamp[TIMESZ], device[DEVSZ], afrbuf[AFRSZ]; static char buf[BUFSZ], timestamp[TIMESZ], device[DEVSZ], afrbuf[AFRSZ];
static union cfu cu; static cu_t cu;
int mtu; int mtu;
while (fgets(buf, BUFSZ-1, stdin)) { while (fgets(buf, BUFSZ-1, stdin)) {
@@ -78,7 +78,7 @@ int main(void)
return 1; return 1;
} }
if (sscanf(buf, "%24s %21s %6299s", timestamp, device, afrbuf) != 3) if (sscanf(buf, "%21s %21s %6299s", timestamp, device, afrbuf) != 3)
return 1; return 1;
mtu = parse_canframe(afrbuf, &cu); mtu = parse_canframe(afrbuf, &cu);
+2 -1
View File
@@ -72,7 +72,8 @@ int mcp251xfd_regmap_read(struct mcp251xfd_priv *priv,
return 0; return 0;
/* maybe it's something like "spi0.0" */ /* maybe it's something like "spi0.0" */
if (strchr(file_path, '/')) tmp = strchr(file_path, '/');
if (tmp)
return -ENOENT; return -ENOENT;
/* first try literally */ /* first try literally */
+1 -6
View File
@@ -160,7 +160,7 @@ static int look_up_uart_speed(long int s)
return B3500000; return B3500000;
#endif #endif
#ifdef B3710000 #ifdef B3710000
case 3710000: case 3710000
return B3710000; return B3710000;
#endif #endif
#ifdef B4000000 #ifdef B4000000
@@ -370,13 +370,8 @@ int main(int argc, char *argv[])
/* retrieve the name of the created CAN netdevice */ /* retrieve the name of the created CAN netdevice */
if (ioctl(fd, SIOCGIFNAME, ifr.ifr_name) < 0) { if (ioctl(fd, SIOCGIFNAME, ifr.ifr_name) < 0) {
if (name) {
perror("ioctl SIOCGIFNAME"); perror("ioctl SIOCGIFNAME");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} else {
/* Graceful degradation: we only needed the name for display. */
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "<unknown>");
}
} }
syslogger(LOG_NOTICE, "attached TTY %s to netdevice %s\n", ttypath, ifr.ifr_name); syslogger(LOG_NOTICE, "attached TTY %s to netdevice %s\n", ttypath, ifr.ifr_name);
+1 -1
View File
@@ -266,7 +266,7 @@ int main(int argc, char *argv[])
fprintf(stderr, "- while (1)\n"); fprintf(stderr, "- while (1)\n");
while (todo_echo || todo_recv) { while (todo_echo || todo_recv) {
/* /*
* reuse peername for storing the sender's peername of * re-use peername for storing the sender's peername of
* received packets * received packets
*/ */
if (verbose) if (verbose)