mirror of
https://github.com/linux-can/can-utils.git
synced 2026-09-21 23:39:58 +02:00
Compare commits
46
Commits
v2025.01
...
b6f20cfe54
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6f20cfe54 | ||
|
|
6b46063eee | ||
|
|
93a7b2dfd3 | ||
|
|
af09afb734 | ||
|
|
69efecc428 | ||
|
|
3698814740 | ||
|
|
6ed0f0ea7f | ||
|
|
287469245c | ||
|
|
7a318636e7 | ||
|
|
7fb81e6779 | ||
|
|
a904183b4e | ||
|
|
e2172546aa | ||
|
|
705b3202a9 | ||
|
|
31a59be02f | ||
|
|
4d908bd7cf | ||
|
|
837e2bb343 | ||
|
|
ec16ef97ff | ||
|
|
651c8818dd | ||
|
|
130e0dced2 | ||
|
|
ff90f4ec21 | ||
|
|
e3ee283443 | ||
|
|
e8130a3575 | ||
|
|
1250c12a30 | ||
|
|
9b5b030877 | ||
|
|
da3914c491 | ||
|
|
18b1e7970a | ||
|
|
491cabea07 | ||
|
|
f1cea504a4 | ||
|
|
900c7e9f6e | ||
|
|
b208876e65 | ||
|
|
72a9fd8ccd | ||
|
|
e448d542e8 | ||
|
|
71b2aec834 | ||
|
|
a24bff8b08 | ||
|
|
fe9ea67814 | ||
|
|
e8559479fb | ||
|
|
6050aa155d | ||
|
|
302184f383 | ||
|
|
c542c9ada7 | ||
|
|
2b8c7c5f4b | ||
|
|
4577316bd6 | ||
|
|
4364d655b8 | ||
|
|
2e71e396c5 | ||
|
|
7815be8741 | ||
|
|
dae324dbd5 | ||
|
|
277048eba6 |
@@ -30,7 +30,45 @@ 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 -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 armhf
|
||||||
|
|
||||||
|
- name: Install Development Packages
|
||||||
|
env:
|
||||||
|
release: ${{ matrix.release == 'debian:experimental' && '-t experimental' || '' }}
|
||||||
|
run: |
|
||||||
|
podman exec -i -u root stable apt update
|
||||||
|
podman exec -e DEBIAN_FRONTEND='noninteractive' -i -u root stable apt upgrade -o APT::Install-Suggests=false -qy
|
||||||
podman exec -e DEBIAN_FRONTEND='noninteractive' -i -u root stable apt install -o APT::Install-Suggests=false -qy ${release} \
|
podman exec -e DEBIAN_FRONTEND='noninteractive' -i -u root stable apt install -o APT::Install-Suggests=false -qy ${release} \
|
||||||
clang \
|
clang \
|
||||||
cmake \
|
cmake \
|
||||||
@@ -38,52 +76,67 @@ jobs:
|
|||||||
gcc-aarch64-linux-gnu \
|
gcc-aarch64-linux-gnu \
|
||||||
gcc-arm-linux-gnueabihf \
|
gcc-arm-linux-gnueabihf \
|
||||||
gcc-mips-linux-gnu \
|
gcc-mips-linux-gnu \
|
||||||
|
libgps-dev \
|
||||||
make
|
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:armhf
|
||||||
|
|
||||||
- name: Configure & Build with gcc
|
- name: Configure & Build with gcc
|
||||||
env:
|
env:
|
||||||
cc: gcc
|
cc: gcc
|
||||||
run: |
|
run: |
|
||||||
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=${cc} -DENABLE_WERROR=ON -B build-${cc}
|
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=${cc} -DENABLE_WERROR=ON -DENABLE_GPS=ON -B build-${cc}
|
||||||
podman exec -i stable cmake --build build-${cc}
|
podman exec -i stable cmake --build build-${cc}
|
||||||
|
|
||||||
- name: Configure & Build with clang
|
- name: Configure & Build with clang
|
||||||
env:
|
env:
|
||||||
cc: clang
|
cc: clang
|
||||||
run: |
|
run: |
|
||||||
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=${cc} -DENABLE_WERROR=ON -B build-${cc}
|
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=${cc} -DENABLE_WERROR=ON -DENABLE_GPS=ON -B build-${cc}
|
||||||
podman exec -i stable cmake --build build-${cc}
|
podman exec -i stable cmake --build build-${cc}
|
||||||
|
|
||||||
- name: Configure & Build with arm-linux-gnueabihf-gcc
|
- name: Configure & Build with arm-linux-gnueabihf-gcc
|
||||||
env:
|
env:
|
||||||
toolchain: arm-linux-gnueabihf-gcc
|
toolchain: arm-linux-gnueabihf-gcc
|
||||||
|
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 -B build-${toolchain}
|
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 --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 -B build-${toolchain}
|
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 --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 -B build-${toolchain}
|
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 --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 -B build-${toolchain}
|
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 --build build-${toolchain}
|
podman exec -i stable cmake --build build-${toolchain}
|
||||||
|
|
||||||
- name: Configure & Build with mips-linux-gnu-gcc
|
- name: Configure & Build with mips-linux-gnu-gcc
|
||||||
@@ -93,6 +146,20 @@ jobs:
|
|||||||
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=cmake/${toolchain}.cmake -DENABLE_WERROR=ON -B build-${toolchain}
|
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=cmake/${toolchain}.cmake -DENABLE_WERROR=ON -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)
|
||||||
|
env:
|
||||||
|
cc: gcc
|
||||||
|
run: |
|
||||||
|
podman exec -i stable make CC=${cc}
|
||||||
|
podman exec -i stable make clean
|
||||||
|
|
||||||
|
- 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() }}
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
*~
|
*~
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
*.o
|
*.o
|
||||||
.ccls-cache
|
.ccls-cache
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles/
|
||||||
|
cmake_install.cmake
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
tags
|
tags
|
||||||
/build
|
/build
|
||||||
@@ -10,6 +16,7 @@ tags
|
|||||||
/can-calc-bit-timing
|
/can-calc-bit-timing
|
||||||
/canbusload
|
/canbusload
|
||||||
/candump
|
/candump
|
||||||
|
/canerrsim
|
||||||
/canfdtest
|
/canfdtest
|
||||||
/cangen
|
/cangen
|
||||||
/cangw
|
/cangw
|
||||||
@@ -33,6 +40,7 @@ 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
|
||||||
|
|||||||
+141
-96
@@ -12,8 +12,38 @@ 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)
|
||||||
@@ -37,24 +67,64 @@ include_directories (./include)
|
|||||||
|
|
||||||
check_function_exists(fork HAVE_FORK)
|
check_function_exists(fork HAVE_FORK)
|
||||||
|
|
||||||
set(PROGRAMS_CANLIB
|
# List of all programs to be built.
|
||||||
asc2log
|
# Each program is expected to have a corresponding source file with the same name.
|
||||||
canbusload
|
set(PROGRAMS)
|
||||||
|
# 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
|
|
||||||
log2long
|
|
||||||
slcanpty
|
|
||||||
)
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(HAVE_FORK)
|
if(ENABLE_IP_SERVER AND HAVE_FORK)
|
||||||
|
list(APPEND PROGRAMS bcmserver)
|
||||||
list(APPEND PROGRAMS_CANLIB canlogserver)
|
list(APPEND PROGRAMS_CANLIB canlogserver)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(PROGRAMS_J1939
|
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)
|
||||||
|
list(APPEND PROGRAMS isotpserver)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_J1939)
|
||||||
|
list(APPEND PROGRAMS_J1939
|
||||||
j1939acd
|
j1939acd
|
||||||
j1939cat
|
j1939cat
|
||||||
j1939spy
|
j1939spy
|
||||||
@@ -62,72 +132,46 @@ set(PROGRAMS_J1939
|
|||||||
testj1939
|
testj1939
|
||||||
)
|
)
|
||||||
|
|
||||||
set(PROGRAMS_J1939_TIMEDATE
|
add_executable(j1939-timedate-cli
|
||||||
j1939-timedate-srv
|
j1939_timedate/j1939_timedate_cli.c
|
||||||
j1939-timedate-cli
|
|
||||||
)
|
)
|
||||||
|
target_link_libraries(j1939-timedate-cli
|
||||||
set(PROGRAMS_ISOBUSFS
|
PRIVATE can j1939
|
||||||
isobusfs-srv
|
|
||||||
isobusfs-cli
|
|
||||||
)
|
)
|
||||||
|
install(TARGETS j1939-timedate-cli DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
|
||||||
set(PROGRAMS
|
add_executable(j1939-timedate-srv
|
||||||
${PROGRAMS_CANLIB}
|
j1939_timedate/j1939_timedate_srv.c
|
||||||
canfdtest
|
|
||||||
cangw
|
|
||||||
cansniffer
|
|
||||||
isotpdump
|
|
||||||
isotpperf
|
|
||||||
isotprecv
|
|
||||||
isotpsend
|
|
||||||
isotpsniffer
|
|
||||||
isotptun
|
|
||||||
slcan_attach
|
|
||||||
slcand
|
|
||||||
)
|
)
|
||||||
|
target_link_libraries(j1939-timedate-srv
|
||||||
if(HAVE_FORK)
|
PRIVATE can j1939
|
||||||
list(APPEND PROGRAMS bcmserver)
|
)
|
||||||
list(APPEND PROGRAMS isotpserver)
|
install(TARGETS j1939-timedate-srv DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(can-calc-bit-timing
|
if(ENABLE_J1939 AND ENABLE_GPS)
|
||||||
calc-bit-timing/can-calc-bit-timing.c
|
add_executable(j1939-vehicle-position-srv
|
||||||
|
j1939_vehicle_position/j1939_vehicle_position_srv.c
|
||||||
)
|
)
|
||||||
|
target_link_libraries(j1939-vehicle-position-srv
|
||||||
add_executable(mcp251xfd-dump
|
PRIVATE can j1939 ${GPS_LIBRARIES}
|
||||||
mcp251xfd/mcp251xfd-dev-coredump.c
|
|
||||||
mcp251xfd/mcp251xfd-dump.c
|
|
||||||
mcp251xfd/mcp251xfd-main.c
|
|
||||||
mcp251xfd/mcp251xfd-regmap.c
|
|
||||||
)
|
)
|
||||||
|
install(TARGETS j1939-vehicle-position-srv DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
if(NOT ANDROID)
|
if(ENABLE_ISOBUSFS)
|
||||||
list(APPEND PROGRAMS ${PROGRAMS_J1939})
|
add_library(isobusfs EXCLUDE_FROM_ALL
|
||||||
|
|
||||||
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
|
||||||
)
|
)
|
||||||
|
|
||||||
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}
|
||||||
@@ -141,10 +185,10 @@ if(NOT ANDROID)
|
|||||||
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
|
||||||
@@ -155,48 +199,55 @@ if(NOT ANDROID)
|
|||||||
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})
|
||||||
install(TARGETS
|
|
||||||
isobusfs-cli
|
|
||||||
isobusfs-srv
|
|
||||||
DESTINATION ${CMAKE_INSTALL_BINDIR})
|
|
||||||
|
|
||||||
set(PUBLIC_HEADER_j1939_TIMEDATE
|
|
||||||
j1939_timedate/j1939_timedate_cmn.h
|
|
||||||
)
|
|
||||||
|
|
||||||
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})
|
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_library(can STATIC
|
if(ENABLE_LOG_FILE)
|
||||||
|
list(APPEND PROGRAMS_CANLIB
|
||||||
|
asc2log
|
||||||
|
log2asc
|
||||||
|
log2long
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_SLCAN)
|
||||||
|
list(APPEND PROGRAMS
|
||||||
|
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
|
||||||
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)
|
||||||
|
|
||||||
@@ -213,12 +264,6 @@ 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"
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ 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. \
|
||||||
@@ -67,6 +68,11 @@ PROGRAMS_J1939_TIMEDATE := \
|
|||||||
j1939-timedate-srv \
|
j1939-timedate-srv \
|
||||||
j1939-timedate-cli
|
j1939-timedate-cli
|
||||||
|
|
||||||
|
ifeq ($(HAVE_LIBGPS),1)
|
||||||
|
PROGRAMS_J1939_VEHICLE_POSITION := \
|
||||||
|
j1939-vehicle-position-srv
|
||||||
|
endif
|
||||||
|
|
||||||
PROGRAMS_ISOBUSFS := \
|
PROGRAMS_ISOBUSFS := \
|
||||||
isobusfs-srv \
|
isobusfs-srv \
|
||||||
isobusfs-cli
|
isobusfs-cli
|
||||||
@@ -98,6 +104,7 @@ PROGRAMS_SLCAN := \
|
|||||||
PROGRAMS := \
|
PROGRAMS := \
|
||||||
$(PROGRAMS_CANGW) \
|
$(PROGRAMS_CANGW) \
|
||||||
$(PROGRAMS_J1939_TIMEDATE) \
|
$(PROGRAMS_J1939_TIMEDATE) \
|
||||||
|
$(PROGRAMS_J1939_VEHICLE_POSITION) \
|
||||||
$(PROGRAMS_ISOBUSFS) \
|
$(PROGRAMS_ISOBUSFS) \
|
||||||
$(PROGRAMS_ISOTP) \
|
$(PROGRAMS_ISOTP) \
|
||||||
$(PROGRAMS_J1939) \
|
$(PROGRAMS_J1939) \
|
||||||
@@ -106,6 +113,7 @@ PROGRAMS := \
|
|||||||
can-calc-bit-timing \
|
can-calc-bit-timing \
|
||||||
canbusload \
|
canbusload \
|
||||||
candump \
|
candump \
|
||||||
|
canerrsim \
|
||||||
canfdtest \
|
canfdtest \
|
||||||
cangen \
|
cangen \
|
||||||
cansequence \
|
cansequence \
|
||||||
@@ -126,7 +134,8 @@ endif
|
|||||||
all: $(PROGRAMS)
|
all: $(PROGRAMS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(PROGRAMS) *.o mcp251xfd/*.o isobusfs/*.o j1939_timedate/*.o
|
rm -f $(PROGRAMS) *.o mcp251xfd/*.o isobusfs/*.o j1939_timedate/*.o \
|
||||||
|
j1939_vehicle_position/*.o
|
||||||
|
|
||||||
install:
|
install:
|
||||||
mkdir -p $(DESTDIR)$(PREFIX)/bin
|
mkdir -p $(DESTDIR)$(PREFIX)/bin
|
||||||
@@ -153,6 +162,8 @@ isobusfs_srv.o: lib.h libj1939.h
|
|||||||
isobusfs_c.o: lib.h libj1939.h
|
isobusfs_c.o: lib.h libj1939.h
|
||||||
j1939_timedate_srv.o: lib.h libj1939.h
|
j1939_timedate_srv.o: lib.h libj1939.h
|
||||||
j1939_timedate_cli.o: lib.h libj1939.h
|
j1939_timedate_cli.o: lib.h libj1939.h
|
||||||
|
j1939_vehicle_position_srv.o: lib.h libj1939.h
|
||||||
|
|
||||||
canframelen.o: canframelen.h
|
canframelen.o: canframelen.h
|
||||||
|
|
||||||
asc2log: asc2log.o lib.o
|
asc2log: asc2log.o lib.o
|
||||||
@@ -182,6 +193,12 @@ j1939-timedate-cli: lib.o \
|
|||||||
j1939_timedate/j1939_timedate_cli.o
|
j1939_timedate/j1939_timedate_cli.o
|
||||||
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
|
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
|
||||||
|
|
||||||
|
j1939-vehicle-position-srv: \
|
||||||
|
lib.o \
|
||||||
|
libj1939.o \
|
||||||
|
j1939_vehicle_position/j1939_vehicle_position_srv.o
|
||||||
|
$(CC) $(LDFLAGS) $^ $(LDLIBS) $(shell pkg-config --libs libgps) -o $@
|
||||||
|
|
||||||
isobusfs-srv: lib.o \
|
isobusfs-srv: lib.o \
|
||||||
libj1939.o \
|
libj1939.o \
|
||||||
isobusfs/isobusfs_cmn.o \
|
isobusfs/isobusfs_cmn.o \
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ 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
|
||||||
@@ -49,6 +50,10 @@ 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
|
||||||
@@ -75,4 +80,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)
|
||||||
|
|||||||
@@ -1121,6 +1121,11 @@ static const unsigned int common_data_bitrates[] = {
|
|||||||
4000000,
|
4000000,
|
||||||
2000000,
|
2000000,
|
||||||
1000000,
|
1000000,
|
||||||
|
800000,
|
||||||
|
500000,
|
||||||
|
250000,
|
||||||
|
125000,
|
||||||
|
100000,
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+564
@@ -0,0 +1,564 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// 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 <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 err_exit(const char *msg)
|
||||||
|
{
|
||||||
|
printf("%s", msg);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void show_custom_format_and_exit(const char *param, const char *format)
|
||||||
|
{
|
||||||
|
char str_buf[80];
|
||||||
|
sprintf(str_buf, format, param);
|
||||||
|
err_exit(str_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void show_invalid_option(const char *option)
|
||||||
|
{
|
||||||
|
show_custom_format_and_exit(option, "Error: Invalid option %s\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void show_err_and_exit(const char *err_type)
|
||||||
|
{
|
||||||
|
show_custom_format_and_exit(err_type, "Error: You can only have one %s parameter!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
char tmp_str[256];
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
// set interface name
|
||||||
|
strcpy(ifr.ifr_name, argv[1]); // can0, vcan0...
|
||||||
|
if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
|
||||||
|
sprintf(tmp_str, "Error setting CAN interface name %s", argv[1]);
|
||||||
|
err_exit(tmp_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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");
|
||||||
|
|
||||||
|
// Send CAN error frame
|
||||||
|
if (write(sock, &frame, sizeof(frame)) < 0)
|
||||||
|
err_exit("Error writing to socket");
|
||||||
|
else
|
||||||
|
printf("CAN error frame sent\n");
|
||||||
|
|
||||||
|
close(sock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -857,7 +857,14 @@ int main(int argc, char **argv)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
int k[] = {1,2};
|
||||||
|
int j = 0;
|
||||||
while (running) {
|
while (running) {
|
||||||
|
ts_gap = double_to_timespec((k[j%2])/1000.0);
|
||||||
|
// printf("%lu, %lu\n", ts_gap.tv_sec, ts_gap.tv_nsec);
|
||||||
|
setsockopt_txtime(s);
|
||||||
|
setup_time();
|
||||||
|
j++;
|
||||||
/* clear values but preserve cu.fd.len */
|
/* clear values but preserve cu.fd.len */
|
||||||
cu.fd.flags = 0;
|
cu.fd.flags = 0;
|
||||||
cu.fd.__res0 = 0;
|
cu.fd.__res0 = 0;
|
||||||
@@ -987,12 +994,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;
|
cu.xl.flags = rnd & (CANXL_SEC | CANXL_RRS);
|
||||||
} 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 ^= CANXL_SEC;
|
xl_flags++;
|
||||||
cu.xl.flags = (xl_flags & CANXL_SEC);
|
cu.xl.flags = (xl_flags & (CANXL_SEC | CANXL_RRS));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* mark CAN XL frame */
|
/* mark CAN XL frame */
|
||||||
|
|||||||
+47
-2
@@ -48,6 +48,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include <linux/can.h>
|
#include <linux/can.h>
|
||||||
#include <linux/can/raw.h>
|
#include <linux/can/raw.h>
|
||||||
@@ -89,6 +90,12 @@ const int canfx_on = 1;
|
|||||||
|
|
||||||
extern int optind, opterr, optopt;
|
extern int optind, opterr, optopt;
|
||||||
|
|
||||||
|
struct sleep {
|
||||||
|
struct timeval *sleep_vector;
|
||||||
|
size_t idx;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
static void print_usage(char *prg)
|
static void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s - replay a compact CAN frame logfile to CAN devices.\n", prg);
|
fprintf(stderr, "%s - replay a compact CAN frame logfile to CAN devices.\n", prg);
|
||||||
@@ -117,6 +124,8 @@ static void print_usage(char *prg)
|
|||||||
"loopback of sent CAN frames)\n");
|
"loopback of sent CAN frames)\n");
|
||||||
fprintf(stderr, " -v (verbose: print "
|
fprintf(stderr, " -v (verbose: print "
|
||||||
"sent CAN frames)\n");
|
"sent CAN frames)\n");
|
||||||
|
fprintf(stderr, " -r (real-time: send "
|
||||||
|
"CAN frames in real-time)\n");
|
||||||
fprintf(stderr, " -h (show "
|
fprintf(stderr, " -h (show "
|
||||||
"this help message)\n\n");
|
"this help message)\n\n");
|
||||||
fprintf(stderr, "Interface assignment:\n");
|
fprintf(stderr, "Interface assignment:\n");
|
||||||
@@ -280,8 +289,11 @@ int main(int argc, char **argv)
|
|||||||
int eof, txmtu, i, j;
|
int eof, txmtu, i, j;
|
||||||
char *fret;
|
char *fret;
|
||||||
unsigned long long sec, usec;
|
unsigned long long sec, usec;
|
||||||
|
bool gap_from_file = false;
|
||||||
|
struct sleep timestamps;
|
||||||
|
struct timeval send_time, act_time, init_trace, init_time;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "I:l:tin:g:s:xvh")) != -1) {
|
while ((opt = getopt(argc, argv, "I:l:tin:g:s:xvrh")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'I':
|
case 'I':
|
||||||
infile = fopen(optarg, "r");
|
infile = fopen(optarg, "r");
|
||||||
@@ -336,6 +348,17 @@ int main(int argc, char **argv)
|
|||||||
verbose++;
|
verbose++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'r':
|
||||||
|
if (isatty(fileno(infile))) {
|
||||||
|
fprintf(stderr, "Specify an input file for option -r !\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
gap_from_file = true; /* using time delta from file */
|
||||||
|
init_trace.tv_sec = 0;
|
||||||
|
init_trace.tv_usec = 0;
|
||||||
|
timestamps.idx = 0; /*to avoid warning accessing idx variable*/
|
||||||
|
break;
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
@@ -368,8 +391,10 @@ int main(int argc, char **argv)
|
|||||||
printf("interactive mode: press ENTER to process next CAN frame ...\n");
|
printf("interactive mode: press ENTER to process next CAN frame ...\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!gap_from_file) {
|
||||||
sleep_ts.tv_sec = gap / 1000;
|
sleep_ts.tv_sec = gap / 1000;
|
||||||
sleep_ts.tv_nsec = (gap % 1000) * 1000000;
|
sleep_ts.tv_nsec = (gap % 1000) * 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
/* open socket */
|
/* open socket */
|
||||||
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
|
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
|
||||||
@@ -548,6 +573,26 @@ int main(int argc, char **argv)
|
|||||||
log_tv.tv_sec = sec;
|
log_tv.tv_sec = sec;
|
||||||
log_tv.tv_usec = usec;
|
log_tv.tv_usec = usec;
|
||||||
|
|
||||||
|
if (gap_from_file){
|
||||||
|
if (timestamps.idx == 0){
|
||||||
|
gettimeofday(&init_time, NULL);
|
||||||
|
if (log_tv.tv_sec > 0 || log_tv.tv_usec > 0)
|
||||||
|
init_trace = log_tv;
|
||||||
|
}
|
||||||
|
timersub(&log_tv, &init_trace, &send_time);
|
||||||
|
|
||||||
|
if (timestamps.idx > 0){
|
||||||
|
gettimeofday(&act_time, NULL);
|
||||||
|
timersub(&act_time, &init_time, &act_time);
|
||||||
|
|
||||||
|
while (timercmp(&act_time, &send_time, <)){
|
||||||
|
gettimeofday(&act_time, NULL);
|
||||||
|
timersub(&act_time, &init_time, &act_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
timestamps.idx++;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ensure the fractions of seconds are 6 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
|
||||||
@@ -570,7 +615,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
} /* while frames_to_send ... */
|
} /* while frames_to_send ... */
|
||||||
|
|
||||||
if (nanosleep(&sleep_ts, NULL))
|
if (!gap_from_file && nanosleep(&sleep_ts, NULL))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
delay_loops++; /* private statistics */
|
delay_loops++; /* private statistics */
|
||||||
|
|||||||
@@ -1077,7 +1077,7 @@ int isobusfs_cli_interactive(struct isobusfs_priv *priv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_int("unknown comand\n");
|
pr_int("unknown command\n");
|
||||||
isobusfs_cli_promt(priv);
|
isobusfs_cli_promt(priv);
|
||||||
} else {
|
} else {
|
||||||
if (errno != EAGAIN && errno != EWOULDBLOCK)
|
if (errno != EAGAIN && errno != EWOULDBLOCK)
|
||||||
|
|||||||
@@ -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 speficic dir */
|
/* expected result \\vol1\~\ not clear if it is manufacture specific dir */
|
||||||
{ "\\~\\", true },
|
{ "\\~\\", true },
|
||||||
/* expected result \\~\ */
|
/* expected result \\~\ */
|
||||||
{ "\\\\~\\", false },
|
{ "\\\\~\\", false },
|
||||||
|
|||||||
@@ -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 wont to stop sending
|
* but it would be nice to have it. Especially if we won't 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)
|
||||||
|
|||||||
@@ -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 acces path %s, for read %s. %s", path,
|
pr_err("failed to access path %s, for read %s. %s", path,
|
||||||
writable ? "and write" : "", strerror(ret));
|
writable ? "and write" : "", strerror(ret));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 withing this
|
* If a client sends a command, which is not defined within 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 */
|
||||||
/* TOOD: actually, this is PGN input filter. Should we use different
|
/* TODO: 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. Wont be able to generate proper manufacturer-specific directory name. Falling mack to MCMC0000");
|
pr_warn("local name is not set. Won't 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:");
|
||||||
|
|||||||
@@ -662,8 +662,8 @@ static int isobusfs_srv_dh_ccd_res(struct isobusfs_srv_priv *priv,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We assime, the relative path stored in res->name is not longer
|
* We assume, the relative path stored in res->name is not longer
|
||||||
* than absolue path
|
* than absolute 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 vor SRC and DST, so we have to do it manually.
|
* -EINVAL for 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;
|
||||||
|
|||||||
@@ -686,7 +686,7 @@ send_response:
|
|||||||
goto free_res;
|
goto free_res;
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_debug("> tx: Read File Response. Error code: %d (%s), readed size: %d",
|
pr_debug("> tx: Read File Response. Error code: %d (%s), read 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:
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+25
@@ -253,6 +253,31 @@ int libj1939_bind_socket(int sock, struct sockaddr_can *addr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* libj1939_connect_socket - Connects a socket to a CAN address.
|
||||||
|
* @sock: The socket file descriptor.
|
||||||
|
* @addr: The CAN address to connect to.
|
||||||
|
*
|
||||||
|
* This function attempts to establish a connection between the given socket
|
||||||
|
* and the specified CAN address. If the connection fails, it logs an error
|
||||||
|
* message with the error code and a description of the error.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, or a negative error code on failure.
|
||||||
|
*/
|
||||||
|
int libj1939_connect_socket(int sock, struct sockaddr_can *addr)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = connect(sock, (void *)addr, sizeof(*addr));
|
||||||
|
if (ret < 0) {
|
||||||
|
ret = -errno;
|
||||||
|
pr_err("failed to connect socket: %d (%s)", ret, strerror(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* libj1939_socket_prio - Set the priority of a J1939 socket
|
* libj1939_socket_prio - Set the priority of a J1939 socket
|
||||||
* @sock: The file descriptor of the socket
|
* @sock: The file descriptor of the socket
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include <linux/can/j1939.h>
|
#include <linux/can/j1939.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <time.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
#ifndef J1939_LIB_H
|
#ifndef J1939_LIB_H
|
||||||
@@ -42,6 +43,7 @@ void libj1939_init_sockaddr_can(struct sockaddr_can *sac, uint32_t pgn);
|
|||||||
|
|
||||||
int libj1939_open_socket(void);
|
int libj1939_open_socket(void);
|
||||||
int libj1939_bind_socket(int sock, struct sockaddr_can *addr);
|
int libj1939_bind_socket(int sock, struct sockaddr_can *addr);
|
||||||
|
int libj1939_connect_socket(int sock, struct sockaddr_can *addr);
|
||||||
int libj1939_socket_prio(int sock, int prio);
|
int libj1939_socket_prio(int sock, int prio);
|
||||||
int libj1939_set_broadcast(int sock);
|
int libj1939_set_broadcast(int sock);
|
||||||
int libj1939_add_socket_to_epoll(int epoll_fd, int sock, uint32_t events);
|
int libj1939_add_socket_to_epoll(int epoll_fd, int sock, uint32_t events);
|
||||||
|
|||||||
@@ -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,8 +370,13 @@ 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
@@ -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) {
|
||||||
/*
|
/*
|
||||||
* re-use peername for storing the sender's peername of
|
* reuse peername for storing the sender's peername of
|
||||||
* received packets
|
* received packets
|
||||||
*/
|
*/
|
||||||
if (verbose)
|
if (verbose)
|
||||||
|
|||||||
Reference in New Issue
Block a user