mirror of
https://github.com/linux-can/can-utils.git
synced 2026-09-20 23:12:09 +02:00
Compare commits
196
Commits
+5
-4
@@ -32,6 +32,7 @@ GNUmakefile.in
|
|||||||
/canlogserver
|
/canlogserver
|
||||||
/canplayer
|
/canplayer
|
||||||
/cansend
|
/cansend
|
||||||
|
/cansequence
|
||||||
/cansniffer
|
/cansniffer
|
||||||
/isotpdump
|
/isotpdump
|
||||||
/isotpperf
|
/isotpperf
|
||||||
@@ -40,10 +41,10 @@ GNUmakefile.in
|
|||||||
/isotpserver
|
/isotpserver
|
||||||
/isotpsniffer
|
/isotpsniffer
|
||||||
/isotptun
|
/isotptun
|
||||||
/jacd
|
/j1939acd
|
||||||
/jcat
|
/j1939cat
|
||||||
/jspy
|
/j1939spy
|
||||||
/jsr
|
/j1939sr
|
||||||
/log2asc
|
/log2asc
|
||||||
/log2long
|
/log2long
|
||||||
/slcan_attach
|
/slcan_attach
|
||||||
|
|||||||
+58
@@ -2,6 +2,9 @@ language: c
|
|||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
|
|
||||||
|
# native
|
||||||
|
|
||||||
- env: test="x64 4.8.4 (make)"
|
- env: test="x64 4.8.4 (make)"
|
||||||
os: linux
|
os: linux
|
||||||
dist: trusty
|
dist: trusty
|
||||||
@@ -47,6 +50,61 @@ matrix:
|
|||||||
- cmake .. -GNinja -DCMAKE_BUILD_TYPE=Debug
|
- cmake .. -GNinja -DCMAKE_BUILD_TYPE=Debug
|
||||||
script: ninja
|
script: ninja
|
||||||
|
|
||||||
|
# ppc64le
|
||||||
|
|
||||||
|
- env: test="ppc64le 4.8.4 (make)"
|
||||||
|
os: linux
|
||||||
|
dist: trusty
|
||||||
|
compiler: gcc
|
||||||
|
script: make
|
||||||
|
arch: ppc64le
|
||||||
|
|
||||||
|
- env: test="ppc64le 4.8.4 (autotools)"
|
||||||
|
os: linux
|
||||||
|
dist: trusty
|
||||||
|
compiler: gcc
|
||||||
|
script: ./autogen.sh && ./configure CFLAGS="-Werror -Wno-unused-result" && make distcheck
|
||||||
|
arch: ppc64le
|
||||||
|
|
||||||
|
- env: test="ppc64le 5.0 (autotools)"
|
||||||
|
os: linux
|
||||||
|
dist: trusty
|
||||||
|
compiler: clang
|
||||||
|
script: ./autogen.sh && ./configure CFLAGS="-Werror -Wno-unused-result" && make distcheck
|
||||||
|
arch: ppc64le
|
||||||
|
|
||||||
|
- env: test="ppc64le 4.8.4 (CMake gcc)"
|
||||||
|
os: linux
|
||||||
|
dist: trusty
|
||||||
|
compiler: gcc
|
||||||
|
before_script:
|
||||||
|
- mkdir gcc_rel && cd gcc_rel
|
||||||
|
- cmake ..
|
||||||
|
script: make
|
||||||
|
arch: ppc64le
|
||||||
|
|
||||||
|
- env: test="ppc64le 5.0 (CMake clang)"
|
||||||
|
os: linux
|
||||||
|
dist: trusty
|
||||||
|
compiler: clang
|
||||||
|
before_script:
|
||||||
|
- mkdir clang_rel && cd clang_rel
|
||||||
|
- cmake ..
|
||||||
|
script: make
|
||||||
|
arch: ppc64le
|
||||||
|
|
||||||
|
- env: test="ppc64le 5.0 (CMake clang - Ninja) Debug"
|
||||||
|
os: linux
|
||||||
|
dist: trusty
|
||||||
|
compiler: clang
|
||||||
|
before_script:
|
||||||
|
- mkdir clang_ninja_dbg && cd clang_ninja_dbg
|
||||||
|
- cmake .. -GNinja -DCMAKE_BUILD_TYPE=Debug
|
||||||
|
script: ninja
|
||||||
|
arch: ppc64le
|
||||||
|
|
||||||
|
# Android
|
||||||
|
|
||||||
- env: test="Android NDK (CMake)"
|
- env: test="Android NDK (CMake)"
|
||||||
os: linux
|
os: linux
|
||||||
language: android
|
language: android
|
||||||
|
|||||||
+150
-2
@@ -1,6 +1,7 @@
|
|||||||
LOCAL_PATH := $(call my-dir)
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
|
||||||
PRIVATE_LOCAL_CFLAGS := -O2 -g -W -Wall \
|
PRIVATE_LOCAL_CFLAGS := -O2 -g -W -Wall \
|
||||||
|
-Wno-error=unused-parameter \
|
||||||
-DSO_RXQ_OVFL=40 \
|
-DSO_RXQ_OVFL=40 \
|
||||||
-DPF_CAN=29 \
|
-DPF_CAN=29 \
|
||||||
-DAF_CAN=PF_CAN
|
-DAF_CAN=PF_CAN
|
||||||
@@ -15,9 +16,104 @@ LOCAL_SRC_FILES := lib.c canframelen.c
|
|||||||
LOCAL_MODULE := libcan
|
LOCAL_MODULE := libcan
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
include $(BUILD_STATIC_LIBRARY)
|
include $(BUILD_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
#
|
||||||
|
# j1939lib
|
||||||
|
#
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := libj1939.c
|
||||||
|
LOCAL_MODULE := libj1939
|
||||||
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
|
include $(BUILD_STATIC_LIBRARY)
|
||||||
|
|
||||||
|
#
|
||||||
|
# j1939acd
|
||||||
|
#
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := j1939acd.c
|
||||||
|
LOCAL_MODULE := j1939acd
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
LOCAL_STATIC_LIBRARIES := libj1939
|
||||||
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
#
|
||||||
|
# j1939cat
|
||||||
|
#
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := j1939cat.c
|
||||||
|
LOCAL_MODULE := j1939cat
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
LOCAL_STATIC_LIBRARIES := libj1939
|
||||||
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
#
|
||||||
|
# j1939spy
|
||||||
|
#
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := j1939spy.c
|
||||||
|
LOCAL_MODULE := j1939spy
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
LOCAL_STATIC_LIBRARIES := libj1939
|
||||||
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
#
|
||||||
|
# j1939sr
|
||||||
|
#
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := j1939sr.c
|
||||||
|
LOCAL_MODULE := j1939sr
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
LOCAL_STATIC_LIBRARIES := libj1939
|
||||||
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
#
|
||||||
|
# testj1939
|
||||||
|
#
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := testj1939.c
|
||||||
|
LOCAL_MODULE := testj1939
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
LOCAL_STATIC_LIBRARIES := libj1939
|
||||||
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
#
|
#
|
||||||
# candump
|
# candump
|
||||||
#
|
#
|
||||||
@@ -30,6 +126,7 @@ LOCAL_MODULE_TAGS := optional
|
|||||||
LOCAL_STATIC_LIBRARIES := libcan
|
LOCAL_STATIC_LIBRARIES := libcan
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
@@ -45,6 +142,21 @@ LOCAL_MODULE_TAGS := optional
|
|||||||
LOCAL_STATIC_LIBRARIES := libcan
|
LOCAL_STATIC_LIBRARIES := libcan
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
#
|
||||||
|
# cansequence
|
||||||
|
#
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := cansequence.c
|
||||||
|
LOCAL_MODULE := cansequence
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
@@ -59,10 +171,10 @@ LOCAL_MODULE := bcmserver
|
|||||||
LOCAL_MODULE_TAGS := optional
|
LOCAL_MODULE_TAGS := optional
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# can-calc-bit-timing
|
# can-calc-bit-timing
|
||||||
#
|
#
|
||||||
@@ -74,6 +186,7 @@ LOCAL_MODULE := can-calc-bit-timing
|
|||||||
LOCAL_MODULE_TAGS := optional
|
LOCAL_MODULE_TAGS := optional
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
@@ -89,6 +202,7 @@ LOCAL_MODULE_TAGS := optional
|
|||||||
LOCAL_STATIC_LIBRARIES := libcan
|
LOCAL_STATIC_LIBRARIES := libcan
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
@@ -103,6 +217,7 @@ LOCAL_MODULE := canfdtest
|
|||||||
LOCAL_MODULE_TAGS := optional
|
LOCAL_MODULE_TAGS := optional
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
@@ -118,6 +233,7 @@ LOCAL_MODULE_TAGS := optional
|
|||||||
LOCAL_STATIC_LIBRARIES := libcan
|
LOCAL_STATIC_LIBRARIES := libcan
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
@@ -132,6 +248,7 @@ LOCAL_MODULE := cangw
|
|||||||
LOCAL_MODULE_TAGS := optional
|
LOCAL_MODULE_TAGS := optional
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
@@ -147,6 +264,7 @@ LOCAL_MODULE_TAGS := optional
|
|||||||
LOCAL_STATIC_LIBRARIES := libcan
|
LOCAL_STATIC_LIBRARIES := libcan
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
@@ -162,6 +280,7 @@ LOCAL_MODULE_TAGS := optional
|
|||||||
LOCAL_STATIC_LIBRARIES := libcan
|
LOCAL_STATIC_LIBRARIES := libcan
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
@@ -176,6 +295,7 @@ LOCAL_MODULE := cansniffer
|
|||||||
LOCAL_MODULE_TAGS := optional
|
LOCAL_MODULE_TAGS := optional
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
@@ -190,6 +310,7 @@ LOCAL_MODULE := isotpdump
|
|||||||
LOCAL_MODULE_TAGS := optional
|
LOCAL_MODULE_TAGS := optional
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
@@ -204,6 +325,7 @@ LOCAL_MODULE := isotprecv
|
|||||||
LOCAL_MODULE_TAGS := optional
|
LOCAL_MODULE_TAGS := optional
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
@@ -218,6 +340,7 @@ LOCAL_MODULE := isotpsend
|
|||||||
LOCAL_MODULE_TAGS := optional
|
LOCAL_MODULE_TAGS := optional
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
@@ -232,6 +355,7 @@ LOCAL_MODULE := isotpserver
|
|||||||
LOCAL_MODULE_TAGS := optional
|
LOCAL_MODULE_TAGS := optional
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
@@ -242,10 +366,11 @@ include $(BUILD_EXECUTABLE)
|
|||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
LOCAL_SRC_FILES := isotpsniffer.c
|
LOCAL_SRC_FILES := isotpsniffer.c
|
||||||
LOCAL_MODULE := isotpsniffer.c
|
LOCAL_MODULE := isotpsniffer
|
||||||
LOCAL_MODULE_TAGS := optional
|
LOCAL_MODULE_TAGS := optional
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
@@ -260,6 +385,7 @@ LOCAL_MODULE := isotptun
|
|||||||
LOCAL_MODULE_TAGS := optional
|
LOCAL_MODULE_TAGS := optional
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
@@ -274,6 +400,7 @@ LOCAL_MODULE := isotpperf
|
|||||||
LOCAL_MODULE_TAGS := optional
|
LOCAL_MODULE_TAGS := optional
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
@@ -289,6 +416,23 @@ LOCAL_MODULE_TAGS := optional
|
|||||||
LOCAL_STATIC_LIBRARIES := libcan
|
LOCAL_STATIC_LIBRARIES := libcan
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
#
|
||||||
|
# asc2log
|
||||||
|
#
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := asc2log.c
|
||||||
|
LOCAL_MODULE := asc2log
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
LOCAL_STATIC_LIBRARIES := libcan
|
||||||
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
@@ -304,6 +448,7 @@ LOCAL_MODULE_TAGS := optional
|
|||||||
LOCAL_STATIC_LIBRARIES := libcan
|
LOCAL_STATIC_LIBRARIES := libcan
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
@@ -318,6 +463,7 @@ LOCAL_MODULE := slcan_attach
|
|||||||
LOCAL_MODULE_TAGS := optional
|
LOCAL_MODULE_TAGS := optional
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
@@ -332,6 +478,7 @@ LOCAL_MODULE := slcand
|
|||||||
LOCAL_MODULE_TAGS := optional
|
LOCAL_MODULE_TAGS := optional
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
@@ -346,5 +493,6 @@ LOCAL_MODULE := slcanpty
|
|||||||
LOCAL_MODULE_TAGS := optional
|
LOCAL_MODULE_TAGS := optional
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
|
||||||
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
|
||||||
|
LOCAL_VENDOR_MODULE := true
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|||||||
+8
-5
@@ -2,13 +2,15 @@ cmake_minimum_required(VERSION 3.3)
|
|||||||
|
|
||||||
project(can-utils LANGUAGES C)
|
project(can-utils LANGUAGES C)
|
||||||
|
|
||||||
|
include (CheckSymbolExists)
|
||||||
include (GNUInstallDirs)
|
include (GNUInstallDirs)
|
||||||
|
|
||||||
if(NOT CMAKE_BUILD_TYPE)
|
if(NOT CMAKE_BUILD_TYPE)
|
||||||
set(CMAKE_BUILD_TYPE Release)
|
set(CMAKE_BUILD_TYPE Release)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
|
check_symbol_exists(__GNU_LIBRARY__ "features.h" _GNU_SOURCE)
|
||||||
|
if(_GNU_SOURCE)
|
||||||
add_definitions(-D_GNU_SOURCE)
|
add_definitions(-D_GNU_SOURCE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -31,15 +33,16 @@ set(PROGRAMS_CANLIB
|
|||||||
canlogserver
|
canlogserver
|
||||||
canplayer
|
canplayer
|
||||||
cansend
|
cansend
|
||||||
|
cansequence
|
||||||
log2asc
|
log2asc
|
||||||
log2long
|
log2long
|
||||||
)
|
)
|
||||||
|
|
||||||
set(PROGRAMS_J1939
|
set(PROGRAMS_J1939
|
||||||
jacd
|
j1939acd
|
||||||
jcat
|
j1939cat
|
||||||
jspy
|
j1939spy
|
||||||
jsr
|
j1939sr
|
||||||
testj1939
|
testj1939
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+9
-8
@@ -50,6 +50,7 @@ bin_PROGRAMS = \
|
|||||||
canlogserver \
|
canlogserver \
|
||||||
canplayer \
|
canplayer \
|
||||||
cansend \
|
cansend \
|
||||||
|
cansequence \
|
||||||
cansniffer \
|
cansniffer \
|
||||||
isotpdump \
|
isotpdump \
|
||||||
isotpperf \
|
isotpperf \
|
||||||
@@ -58,10 +59,10 @@ bin_PROGRAMS = \
|
|||||||
isotpserver \
|
isotpserver \
|
||||||
isotpsniffer \
|
isotpsniffer \
|
||||||
isotptun \
|
isotptun \
|
||||||
jacd \
|
j1939acd \
|
||||||
jcat \
|
j1939cat \
|
||||||
jspy \
|
j1939spy \
|
||||||
jsr \
|
j1939sr \
|
||||||
log2asc \
|
log2asc \
|
||||||
log2long \
|
log2long \
|
||||||
slcan_attach \
|
slcan_attach \
|
||||||
@@ -69,10 +70,10 @@ bin_PROGRAMS = \
|
|||||||
slcanpty \
|
slcanpty \
|
||||||
testj1939
|
testj1939
|
||||||
|
|
||||||
jacd_LDADD = libj1939.la
|
j1939acd_LDADD = libj1939.la
|
||||||
jcat_LDADD = libj1939.la
|
j1939cat_LDADD = libj1939.la
|
||||||
jspy_LDADD = libj1939.la
|
j1939spy_LDADD = libj1939.la
|
||||||
jsr_LDADD = libj1939.la
|
j1939sr_LDADD = libj1939.la
|
||||||
testj1939_LDADD = libj1939.la
|
testj1939_LDADD = libj1939.la
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
|
|||||||
@@ -67,10 +67,10 @@ PROGRAMS_ISOTP := \
|
|||||||
isotptun
|
isotptun
|
||||||
|
|
||||||
PROGRAMS_J1939 := \
|
PROGRAMS_J1939 := \
|
||||||
jacd \
|
j1939acd \
|
||||||
jcat \
|
j1939cat \
|
||||||
jspy \
|
j1939spy \
|
||||||
jsr \
|
j1939sr \
|
||||||
testj1939
|
testj1939
|
||||||
|
|
||||||
PROGRAMS_SLCAN := \
|
PROGRAMS_SLCAN := \
|
||||||
@@ -89,6 +89,7 @@ PROGRAMS := \
|
|||||||
candump \
|
candump \
|
||||||
canfdtest \
|
canfdtest \
|
||||||
cangen \
|
cangen \
|
||||||
|
cansequence \
|
||||||
canlogserver \
|
canlogserver \
|
||||||
canplayer \
|
canplayer \
|
||||||
cansend \
|
cansend \
|
||||||
@@ -116,12 +117,13 @@ cangen.o: lib.h
|
|||||||
canlogserver.o: lib.h
|
canlogserver.o: lib.h
|
||||||
canplayer.o: lib.h
|
canplayer.o: lib.h
|
||||||
cansend.o: lib.h
|
cansend.o: lib.h
|
||||||
|
cansequence.o: lib.h
|
||||||
log2asc.o: lib.h
|
log2asc.o: lib.h
|
||||||
log2long.o: lib.h
|
log2long.o: lib.h
|
||||||
jacd.o: libj1939.h
|
j1939acd.o: libj1939.h
|
||||||
jcat.o: libj1939.h
|
j1939cat.o: libj1939.h
|
||||||
jspy.o: libj1939.h
|
j1939spy.o: libj1939.h
|
||||||
jsr.o: libj1939.h
|
j1939sr.o: libj1939.h
|
||||||
testj1939.o: libj1939.h
|
testj1939.o: libj1939.h
|
||||||
canframelen.o: canframelen.h
|
canframelen.o: canframelen.h
|
||||||
|
|
||||||
@@ -131,11 +133,12 @@ cangen: cangen.o lib.o
|
|||||||
canlogserver: canlogserver.o lib.o
|
canlogserver: canlogserver.o lib.o
|
||||||
canplayer: canplayer.o lib.o
|
canplayer: canplayer.o lib.o
|
||||||
cansend: cansend.o lib.o
|
cansend: cansend.o lib.o
|
||||||
|
cansequence: cansequence.o lib.o
|
||||||
log2asc: log2asc.o lib.o
|
log2asc: log2asc.o lib.o
|
||||||
log2long: log2long.o lib.o
|
log2long: log2long.o lib.o
|
||||||
jacd: jacd.o libj1939.o
|
j1939acd: j1939acd.o libj1939.o
|
||||||
jcat: jcat.o libj1939.o
|
j1939cat: j1939cat.o libj1939.o
|
||||||
jspy: jspy.o libj1939.o
|
j1939spy: j1939spy.o libj1939.o
|
||||||
jsr: jsr.o libj1939.o
|
j1939sr: j1939sr.o libj1939.o
|
||||||
testj1939: testj1939.o libj1939.o
|
testj1939: testj1939.o libj1939.o
|
||||||
canbusload: canbusload.o canframelen.o
|
canbusload: canbusload.o canframelen.o
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ subsystem (aka SocketCAN):
|
|||||||
* canplayer : replay CAN logfiles
|
* canplayer : replay CAN logfiles
|
||||||
* cansend : send a single frame
|
* cansend : send a single frame
|
||||||
* cangen : generate (random) CAN traffic
|
* cangen : generate (random) CAN traffic
|
||||||
* cansniffer : display CAN data content differences (just 11bit CAN IDs)
|
* cansequence : send and check sequence of CAN frames with incrementing payload
|
||||||
|
* cansniffer : display CAN data content differences
|
||||||
|
|
||||||
#### CAN access via IP sockets
|
#### CAN access via IP sockets
|
||||||
* canlogserver : log CAN frames from a remote/local host
|
* canlogserver : log CAN frames from a remote/local host
|
||||||
@@ -38,6 +39,16 @@ subsystem (aka SocketCAN):
|
|||||||
* isotpperf : ISO15765-2 protocol performance visualisation
|
* isotpperf : ISO15765-2 protocol performance visualisation
|
||||||
* isotptun : create a bi-directional IP tunnel on CAN via ISO-TP
|
* isotptun : create a bi-directional IP tunnel on CAN via ISO-TP
|
||||||
|
|
||||||
|
#### J1939/ISOBus tools
|
||||||
|
* j1939acd : address claim daemon
|
||||||
|
* j1939cat : take a file and send and receive it over CAN
|
||||||
|
* j1939spy : spy on J1939 messages using SOC_J1939
|
||||||
|
* j1939sr : send/recv from stdin or to stdout
|
||||||
|
* testj1939 : send/receive test packet
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
#### 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
|
||||||
|
|||||||
@@ -42,44 +42,47 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <locale.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <libgen.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <locale.h>
|
|
||||||
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <linux/can.h>
|
#include <linux/can.h>
|
||||||
#include <linux/can/error.h>
|
#include <linux/can/error.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
|
|
||||||
|
#define BUFLEN 400 /* CAN FD mode lines can be pretty long */
|
||||||
|
|
||||||
extern int optind, opterr, optopt;
|
extern int optind, opterr, optopt;
|
||||||
|
|
||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
|
fprintf(stderr, "%s - convert ASC logfile to compact CAN frame logfile.\n", prg);
|
||||||
fprintf(stderr, "Usage: %s\n", prg);
|
fprintf(stderr, "Usage: %s\n", prg);
|
||||||
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
|
fprintf(stderr, "Options:\n");
|
||||||
fprintf(stderr, " -O <outfile> (default stdout)\n");
|
fprintf(stderr, "\t-I <infile>\t(default stdin)\n");
|
||||||
|
fprintf(stderr, "\t-O <outfile>\t(default stdout)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void prframe(FILE *file, struct timeval *tv, int dev, struct can_frame *cf) {
|
void prframe(FILE *file, struct timeval *tv, int dev, struct canfd_frame *cf, unsigned int max_dlen, char *extra_info) {
|
||||||
|
|
||||||
fprintf(file, "(%ld.%06ld) ", tv->tv_sec, tv->tv_usec);
|
fprintf(file, "(%lu.%06lu) ", tv->tv_sec, tv->tv_usec);
|
||||||
|
|
||||||
if (dev > 0)
|
if (dev > 0)
|
||||||
fprintf(file, "can%d ", dev-1);
|
fprintf(file, "can%d ", dev-1);
|
||||||
else
|
else
|
||||||
fprintf(file, "canX ");
|
fprintf(file, "canX ");
|
||||||
|
|
||||||
/* no CAN FD support so far */
|
fprint_canframe(file, cf, extra_info, 0, max_dlen);
|
||||||
fprint_canframe(file, (struct canfd_frame *)cf, "\n", 0, CAN_MAX_DLEN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_can_id(struct can_frame *cf, char *idstring, int base) {
|
void get_can_id(struct canfd_frame *cf, char *idstring, int base) {
|
||||||
|
|
||||||
if (idstring[strlen(idstring)-1] == 'x') {
|
if (idstring[strlen(idstring)-1] == 'x') {
|
||||||
cf->can_id = CAN_EFF_FLAG;
|
cf->can_id = CAN_EFF_FLAG;
|
||||||
@@ -122,14 +125,224 @@ void calc_tv(struct timeval *tv, struct timeval *read_tv,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void eval_can(char* buf, struct timeval *date_tvp, char timestamps, char base, int dplace, FILE *outfile) {
|
||||||
|
|
||||||
|
int interface;
|
||||||
|
static struct timeval tv; /* current frame timestamp */
|
||||||
|
static struct timeval read_tv; /* frame timestamp from ASC file */
|
||||||
|
struct canfd_frame cf;
|
||||||
|
char rtr;
|
||||||
|
int dlc = 0;
|
||||||
|
int data[8];
|
||||||
|
char tmp1[BUFLEN];
|
||||||
|
char dir[3]; /* 'Rx' or 'Tx' plus terminating zero */
|
||||||
|
char *extra_info;
|
||||||
|
int i, items, found;
|
||||||
|
|
||||||
|
/* 0.002367 1 390x Rx d 8 17 00 14 00 C0 00 08 00 */
|
||||||
|
|
||||||
|
found = 0; /* found valid CAN frame ? */
|
||||||
|
|
||||||
|
if (base == 'h') { /* check for CAN frames with hexadecimal values */
|
||||||
|
|
||||||
|
items = sscanf(buf, "%lu.%lu %d %s %2s %c %d %x %x %x %x %x %x %x %x",
|
||||||
|
&read_tv.tv_sec, &read_tv.tv_usec, &interface,
|
||||||
|
tmp1, dir, &rtr, &dlc,
|
||||||
|
&data[0], &data[1], &data[2], &data[3],
|
||||||
|
&data[4], &data[5], &data[6], &data[7]);
|
||||||
|
|
||||||
|
if ((items == dlc + 7 ) || /* data frame */
|
||||||
|
((items == 6) && (rtr == 'r')) || /* RTR without DLC */
|
||||||
|
((items == 7) && (rtr == 'r'))) { /* RTR with DLC */
|
||||||
|
found = 1;
|
||||||
|
get_can_id(&cf, tmp1, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else { /* check for CAN frames with decimal values */
|
||||||
|
|
||||||
|
items = sscanf(buf, "%lu.%lu %d %s %2s %c %d %d %d %d %d %d %d %d %d",
|
||||||
|
&read_tv.tv_sec, &read_tv.tv_usec, &interface,
|
||||||
|
tmp1, dir, &rtr, &dlc,
|
||||||
|
&data[0], &data[1], &data[2], &data[3],
|
||||||
|
&data[4], &data[5], &data[6], &data[7]);
|
||||||
|
|
||||||
|
if ((items == dlc + 7 ) || /* data frame */
|
||||||
|
((items == 6) && (rtr == 'r')) || /* RTR without DLC */
|
||||||
|
((items == 7) && (rtr == 'r'))) { /* RTR with DLC */
|
||||||
|
found = 1;
|
||||||
|
get_can_id(&cf, tmp1, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
|
||||||
|
if (dlc > CAN_MAX_DLC)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (strlen(dir) != 2) /* "Rx" or "Tx" */
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (dir[0] == 'R')
|
||||||
|
extra_info = " R\n";
|
||||||
|
else
|
||||||
|
extra_info = " T\n";
|
||||||
|
|
||||||
|
cf.len = dlc;
|
||||||
|
if (rtr == 'r')
|
||||||
|
cf.can_id |= CAN_RTR_FLAG;
|
||||||
|
else
|
||||||
|
for (i = 0; i < dlc; i++)
|
||||||
|
cf.data[i] = data[i] & 0xFFU;
|
||||||
|
|
||||||
|
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
||||||
|
prframe(outfile, &tv, interface, &cf, CAN_MAX_DLEN, extra_info);
|
||||||
|
fflush(outfile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for ErrorFrames */
|
||||||
|
if (sscanf(buf, "%lu.%lu %d %s",
|
||||||
|
&read_tv.tv_sec, &read_tv.tv_usec,
|
||||||
|
&interface, tmp1) == 4) {
|
||||||
|
|
||||||
|
if (!strncmp(tmp1, "ErrorFrame", strlen("ErrorFrame"))) {
|
||||||
|
|
||||||
|
memset(&cf, 0, sizeof(cf));
|
||||||
|
/* do not know more than 'Error' */
|
||||||
|
cf.can_id = (CAN_ERR_FLAG | CAN_ERR_BUSERROR);
|
||||||
|
cf.len = CAN_ERR_DLC;
|
||||||
|
|
||||||
|
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
||||||
|
prframe(outfile, &tv, interface, &cf, CAN_MAX_DLEN, "\n");
|
||||||
|
fflush(outfile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps, int dplace, FILE *outfile) {
|
||||||
|
|
||||||
|
int interface;
|
||||||
|
static struct timeval tv; /* current frame timestamp */
|
||||||
|
static struct timeval read_tv; /* frame timestamp from ASC file */
|
||||||
|
struct canfd_frame cf = { 0 };
|
||||||
|
unsigned char brs, esi, ctmp;
|
||||||
|
unsigned int flags;
|
||||||
|
int dlc, dlen = 0;
|
||||||
|
char tmp1[BUFLEN];
|
||||||
|
char dir[3]; /* 'Rx' or 'Tx' plus terminating zero */
|
||||||
|
char *extra_info;
|
||||||
|
char *ptr;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* The CANFD format is mainly in hex representation but <DataLength>
|
||||||
|
and probably some content we skip anyway. Don't trust the docs! */
|
||||||
|
|
||||||
|
/* 21.671796 CANFD 1 Tx 11 msgCanFdFr1 1 0 a 16 \
|
||||||
|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 59 c0 \
|
||||||
|
100000 214 223040 80000000 46500250 460a0250 20011736 20010205 */
|
||||||
|
|
||||||
|
/* check for valid line without symbolic name */
|
||||||
|
if (sscanf(buf, "%lu.%lu %*s %d %2s %s %hhx %hhx %x %d ",
|
||||||
|
&read_tv.tv_sec, &read_tv.tv_usec, &interface,
|
||||||
|
dir, tmp1, &brs, &esi, &dlc, &dlen) != 9) {
|
||||||
|
|
||||||
|
/* check for valid line with a symbolic name */
|
||||||
|
if (sscanf(buf, "%lu.%lu %*s %d %2s %s %*s %hhx %hhx %x %d ",
|
||||||
|
&read_tv.tv_sec, &read_tv.tv_usec, &interface,
|
||||||
|
dir, tmp1, &brs, &esi, &dlc, &dlen) != 9) {
|
||||||
|
|
||||||
|
/* no valid CANFD format pattern */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for allowed (unsigned) value ranges */
|
||||||
|
if ((dlen > CANFD_MAX_DLEN) || (dlc > CANFD_MAX_DLC) ||
|
||||||
|
(brs > 1) || (esi > 1))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (strlen(dir) != 2) /* "Rx" or "Tx" */
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (dir[0] == 'R')
|
||||||
|
extra_info = " R\n";
|
||||||
|
else
|
||||||
|
extra_info = " T\n";
|
||||||
|
|
||||||
|
/* don't trust ASCII content - sanitize data length */
|
||||||
|
if (dlen != can_dlc2len(can_len2dlc(dlen)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
get_can_id(&cf, tmp1, 16);
|
||||||
|
|
||||||
|
/* now search for the beginning of the data[] content */
|
||||||
|
sprintf(tmp1, " %x %x %x %2d ", brs, esi, dlc, dlen);
|
||||||
|
|
||||||
|
/* search for the pattern generated by real data */
|
||||||
|
ptr = strcasestr(buf, tmp1);
|
||||||
|
if (ptr == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ptr += strlen(tmp1); /* start of ASCII hex frame data */
|
||||||
|
|
||||||
|
cf.len = dlen;
|
||||||
|
|
||||||
|
for (i = 0; i < dlen; i++) {
|
||||||
|
ctmp = asc2nibble(ptr[0]);
|
||||||
|
if (ctmp > 0x0F)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cf.data[i] = (ctmp << 4);
|
||||||
|
|
||||||
|
ctmp = asc2nibble(ptr[1]);
|
||||||
|
if (ctmp > 0x0F)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cf.data[i] |= ctmp;
|
||||||
|
|
||||||
|
ptr += 3; /* start of next ASCII hex byte */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip MessageDuration and MessageLength to get Flags value */
|
||||||
|
if (sscanf(ptr, " %*x %*x %x ", &flags) != 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* relevant flags in Flags field */
|
||||||
|
#define ASC_F_RTR 0x00000010
|
||||||
|
#define ASC_F_FDF 0x00001000
|
||||||
|
#define ASC_F_BRS 0x00002000
|
||||||
|
#define ASC_F_ESI 0x00004000
|
||||||
|
|
||||||
|
if (flags & ASC_F_FDF) {
|
||||||
|
dlen = CANFD_MAX_DLEN;
|
||||||
|
if (flags & ASC_F_BRS)
|
||||||
|
cf.flags |= CANFD_BRS;
|
||||||
|
if (flags & ASC_F_ESI)
|
||||||
|
cf.flags |= CANFD_ESI;
|
||||||
|
} else {
|
||||||
|
/* yes. The 'CANFD' format supports classic CAN content! */
|
||||||
|
dlen = CAN_MAX_DLEN;
|
||||||
|
if (flags & ASC_F_RTR) {
|
||||||
|
cf.can_id |= CAN_RTR_FLAG;
|
||||||
|
/* dlen is always 0 for classic CAN RTR frames
|
||||||
|
but the DLC value is valid in RTR cases */
|
||||||
|
cf.len = dlc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
||||||
|
prframe(outfile, &tv, interface, &cf, dlen, extra_info);
|
||||||
|
fflush(outfile);
|
||||||
|
|
||||||
|
/* No support for really strange CANFD ErrorFrames format m( */
|
||||||
|
}
|
||||||
|
|
||||||
int get_date(struct timeval *tv, char *date) {
|
int get_date(struct timeval *tv, char *date) {
|
||||||
|
|
||||||
char ctmp[10];
|
|
||||||
int itmp;
|
|
||||||
|
|
||||||
struct tm tms;
|
struct tm tms;
|
||||||
|
unsigned int msecs = 0;
|
||||||
|
|
||||||
if (sscanf(date, "%9s %d %9s %9s %d", ctmp, &itmp, ctmp, ctmp, &itmp) == 5) {
|
if (strcasestr(date, " pm ") != NULL) {
|
||||||
/* assume EN/US date due to existing am/pm field */
|
/* assume EN/US date due to existing am/pm field */
|
||||||
|
|
||||||
if (!setlocale(LC_TIME, "en_US")) {
|
if (!setlocale(LC_TIME, "en_US")) {
|
||||||
@@ -137,29 +350,39 @@ int get_date(struct timeval *tv, char *date) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strptime(date, "%B %d %r %Y", &tms))
|
if (!strptime(date, "%B %d %I:%M:%S %p %Y", &tms)) {
|
||||||
|
/* The string might contain a milliseconds value which strptime()
|
||||||
|
does not support. So we read the ms value into the year variable
|
||||||
|
before parsing the real year value (hack) */
|
||||||
|
if (!strptime(date, "%B %d %I:%M:%S.%Y %p %Y", &tms))
|
||||||
return 1;
|
return 1;
|
||||||
|
sscanf(date, "%*s %*d %*d:%*d:%*d.%3u ", &msecs);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* assume DE date due to non existing am/pm field */
|
/* assume DE date due to non existing am/pm field */
|
||||||
|
|
||||||
if (sscanf(date, "%9s %d %9s %d", ctmp, &itmp, ctmp, &itmp) != 4)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (!setlocale(LC_TIME, "de_DE")) {
|
if (!setlocale(LC_TIME, "de_DE")) {
|
||||||
fprintf(stderr, "Setting locale to 'de_DE' failed!\n");
|
fprintf(stderr, "Setting locale to 'de_DE' failed!\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strptime(date, "%B %d %T %Y", &tms))
|
if (!strptime(date, "%B %d %H:%M:%S %Y", &tms)) {
|
||||||
|
/* The string might contain a milliseconds value which strptime()
|
||||||
|
does not support. So we read the ms value into the year variable
|
||||||
|
before parsing the real year value (hack) */
|
||||||
|
if (!strptime(date, "%B %d %H:%M:%S.%Y %Y", &tms))
|
||||||
return 1;
|
return 1;
|
||||||
|
sscanf(date, "%*s %*d %*d:%*d:%*d.%3u ", &msecs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//printf("h %d m %d s %d d %d m %d y %d\n",
|
//printf("h %d m %d s %d ms %03d d %d m %d y %d\n",
|
||||||
//tms.tm_hour, tms.tm_min, tms.tm_sec,
|
//tms.tm_hour, tms.tm_min, tms.tm_sec, msecs,
|
||||||
//tms.tm_mday, tms.tm_mon+1, tms.tm_year+1900);
|
//tms.tm_mday, tms.tm_mon+1, tms.tm_year+1900);
|
||||||
|
|
||||||
tv->tv_sec = mktime(&tms);
|
tv->tv_sec = mktime(&tms);
|
||||||
|
tv->tv_usec = msecs * 1000;
|
||||||
|
|
||||||
if (tv->tv_sec < 0)
|
if (tv->tv_sec < 0)
|
||||||
return 1;
|
return 1;
|
||||||
@@ -169,24 +392,17 @@ int get_date(struct timeval *tv, char *date) {
|
|||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char buf[100], tmp1[100], tmp2[100];
|
char buf[BUFLEN], tmp1[BUFLEN], tmp2[BUFLEN];
|
||||||
|
|
||||||
FILE *infile = stdin;
|
FILE *infile = stdin;
|
||||||
FILE *outfile = stdout;
|
FILE *outfile = stdout;
|
||||||
static int verbose;
|
static int verbose;
|
||||||
struct can_frame cf;
|
static struct timeval tmp_tv; /* tmp frame timestamp from ASC file */
|
||||||
static struct timeval tv; /* current frame timestamp */
|
|
||||||
static struct timeval read_tv; /* frame timestamp from ASC file */
|
|
||||||
static struct timeval date_tv; /* date of the ASC file */
|
static struct timeval date_tv; /* date of the ASC file */
|
||||||
static int dplace; /* decimal place 4, 5 or 6 or uninitialized */
|
static int dplace; /* decimal place 4, 5 or 6 or uninitialized */
|
||||||
static char base; /* 'd'ec or 'h'ex */
|
static char base; /* 'd'ec or 'h'ex */
|
||||||
static char timestamps; /* 'a'bsolute or 'r'elative */
|
static char timestamps; /* 'a'bsolute or 'r'elative */
|
||||||
|
int opt;
|
||||||
int interface;
|
|
||||||
char rtr;
|
|
||||||
int dlc = 0;
|
|
||||||
int data[8];
|
|
||||||
int i, found, opt;
|
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "I:O:v?")) != -1) {
|
while ((opt = getopt(argc, argv, "I:O:v?")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
@@ -224,7 +440,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
while (fgets(buf, 99, infile)) {
|
while (fgets(buf, BUFLEN-1, infile)) {
|
||||||
|
|
||||||
if (!dplace) { /* the representation of a valid CAN frame not known */
|
if (!dplace) { /* the representation of a valid CAN frame not known */
|
||||||
|
|
||||||
@@ -259,87 +475,35 @@ int main(int argc, char **argv)
|
|||||||
gettimeofday(&date_tv, NULL);
|
gettimeofday(&date_tv, NULL);
|
||||||
}
|
}
|
||||||
if (verbose)
|
if (verbose)
|
||||||
printf("date %ld => %s", date_tv.tv_sec, ctime(&date_tv.tv_sec));
|
printf("date %lu => %s", date_tv.tv_sec, ctime(&date_tv.tv_sec));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for decimal places length in valid CAN frames */
|
/* check for decimal places length in valid CAN frames */
|
||||||
if (sscanf(buf, "%ld.%s %d ", &tv.tv_sec, tmp2, &i) == 3){
|
if (sscanf(buf, "%lu.%s %s ", &tmp_tv.tv_sec, tmp2,
|
||||||
|
tmp1) != 3)
|
||||||
|
continue; /* dplace remains zero until first found CAN frame */
|
||||||
|
|
||||||
dplace = strlen(tmp2);
|
dplace = strlen(tmp2);
|
||||||
if (verbose)
|
if (verbose)
|
||||||
printf("decimal place %d, e.g. '%s'\n", dplace, tmp2);
|
printf("decimal place %d, e.g. '%s'\n", dplace,
|
||||||
|
tmp2);
|
||||||
if (dplace < 4 || dplace > 6) {
|
if (dplace < 4 || dplace > 6) {
|
||||||
printf("invalid dplace %d (must be 4, 5 or 6)!\n", dplace);
|
printf("invalid dplace %d (must be 4, 5 or 6)!\n",
|
||||||
|
dplace);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else
|
|
||||||
continue; /* dplace remains zero until first found CAN frame */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the representation of a valid CAN frame is known here */
|
/* the representation of a valid CAN frame is known here */
|
||||||
/* so try to get CAN frames and ErrorFrames and convert them */
|
/* so try to get CAN frames and ErrorFrames and convert them */
|
||||||
|
|
||||||
/* 0.002367 1 390x Rx d 8 17 00 14 00 C0 00 08 00 */
|
/* check classic CAN format or the CANFD tag which can take both types */
|
||||||
|
if (sscanf(buf, "%lu.%lu %s ", &tmp_tv.tv_sec, &tmp_tv.tv_usec, tmp1) == 3){
|
||||||
found = 0; /* found valid CAN frame ? */
|
if (!strncmp(tmp1, "CANFD", 5))
|
||||||
|
eval_canfd(buf, &date_tv, timestamps, dplace, outfile);
|
||||||
if (base == 'h') { /* check for CAN frames with hexadecimal values */
|
else
|
||||||
|
eval_can(buf, &date_tv, timestamps, base, dplace, outfile);
|
||||||
if (sscanf(buf, "%ld.%ld %d %s %*s %c %d %x %x %x %x %x %x %x %x",
|
|
||||||
&read_tv.tv_sec, &read_tv.tv_usec, &interface,
|
|
||||||
tmp1, &rtr, &dlc,
|
|
||||||
&data[0], &data[1], &data[2], &data[3],
|
|
||||||
&data[4], &data[5], &data[6], &data[7]
|
|
||||||
) == dlc + 6 ) {
|
|
||||||
|
|
||||||
found = 1;
|
|
||||||
get_can_id(&cf, tmp1, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else { /* check for CAN frames with decimal values */
|
|
||||||
|
|
||||||
if (sscanf(buf, "%ld.%ld %d %s %*s %c %d %d %d %d %d %d %d %d %d",
|
|
||||||
&read_tv.tv_sec, &read_tv.tv_usec, &interface,
|
|
||||||
tmp1, &rtr, &dlc,
|
|
||||||
&data[0], &data[1], &data[2], &data[3],
|
|
||||||
&data[4], &data[5], &data[6], &data[7]
|
|
||||||
) == dlc + 6 ) {
|
|
||||||
|
|
||||||
found = 1;
|
|
||||||
get_can_id(&cf, tmp1, 10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found) {
|
|
||||||
if (rtr == 'r')
|
|
||||||
cf.can_id |= CAN_RTR_FLAG;
|
|
||||||
|
|
||||||
cf.can_dlc = dlc & 0x0FU;
|
|
||||||
for (i=0; i<dlc; i++)
|
|
||||||
cf.data[i] = data[i] & 0xFFU;
|
|
||||||
|
|
||||||
calc_tv(&tv, &read_tv, &date_tv, timestamps, dplace);
|
|
||||||
prframe(outfile, &tv, interface, &cf);
|
|
||||||
fflush(outfile);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check for ErrorFrames */
|
|
||||||
if (sscanf(buf, "%ld.%ld %d %s",
|
|
||||||
&read_tv.tv_sec, &read_tv.tv_usec,
|
|
||||||
&interface, tmp1) == 4) {
|
|
||||||
|
|
||||||
if (!strncmp(tmp1, "ErrorFrame", strlen("ErrorFrame"))) {
|
|
||||||
|
|
||||||
memset(&cf, 0, sizeof(cf));
|
|
||||||
/* do not know more than 'Error' */
|
|
||||||
cf.can_id = (CAN_ERR_FLAG | CAN_ERR_BUSERROR);
|
|
||||||
cf.can_dlc = CAN_ERR_DLC;
|
|
||||||
|
|
||||||
calc_tv(&tv, &read_tv, &date_tv, timestamps, dplace);
|
|
||||||
prframe(outfile, &tv, interface, &cf);
|
|
||||||
fflush(outfile);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(outfile);
|
fclose(outfile);
|
||||||
|
|||||||
+17
-14
@@ -108,20 +108,21 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <signal.h>
|
#include <time.h>
|
||||||
#include <errno.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/uio.h>
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#include <linux/can.h>
|
#include <linux/can.h>
|
||||||
#include <linux/can/bcm.h>
|
#include <linux/can/bcm.h>
|
||||||
@@ -135,7 +136,7 @@ void childdied(int i)
|
|||||||
wait(NULL);
|
wait(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
int sl, sa, sc;
|
int sl, sa, sc;
|
||||||
@@ -180,8 +181,12 @@ int main(int argc, char **argv)
|
|||||||
saddr.sin_port = htons(PORT);
|
saddr.sin_port = htons(PORT);
|
||||||
|
|
||||||
while(bind(sl,(struct sockaddr*)&saddr, sizeof(saddr)) < 0) {
|
while(bind(sl,(struct sockaddr*)&saddr, sizeof(saddr)) < 0) {
|
||||||
|
struct timespec f = {
|
||||||
|
.tv_nsec = 100 * 1000 * 1000,
|
||||||
|
};
|
||||||
|
|
||||||
printf(".");fflush(NULL);
|
printf(".");fflush(NULL);
|
||||||
usleep(100000);
|
nanosleep(&f, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listen(sl,3) != 0) {
|
if (listen(sl,3) != 0) {
|
||||||
@@ -192,11 +197,9 @@ int main(int argc, char **argv)
|
|||||||
while (1) {
|
while (1) {
|
||||||
sa = accept(sl,(struct sockaddr *)&clientaddr, &sin_size);
|
sa = accept(sl,(struct sockaddr *)&clientaddr, &sin_size);
|
||||||
if (sa > 0 ){
|
if (sa > 0 ){
|
||||||
|
if (!fork())
|
||||||
if (fork())
|
|
||||||
close(sa);
|
|
||||||
else
|
|
||||||
break;
|
break;
|
||||||
|
close(sa);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (errno != EINTR) {
|
if (errno != EINTR) {
|
||||||
|
|||||||
+26
-15
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <libgen.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -25,8 +26,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <linux/types.h>
|
|
||||||
#include <linux/can/netlink.h>
|
#include <linux/can/netlink.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
/* imported from kernel */
|
/* imported from kernel */
|
||||||
|
|
||||||
@@ -131,17 +132,16 @@ static inline void *netdev_priv(const struct net_device *dev)
|
|||||||
|
|
||||||
static void print_usage(char *cmd)
|
static void print_usage(char *cmd)
|
||||||
{
|
{
|
||||||
|
printf("%s - calculate CAN bit timing parameters.\n", cmd);
|
||||||
printf("Usage: %s [options] [<CAN-contoller-name>]\n"
|
printf("Usage: %s [options] [<CAN-contoller-name>]\n"
|
||||||
"\tOptions:\n"
|
"Options:\n"
|
||||||
"\t-q : don't print header line\n"
|
"\t-q don't print header line\n"
|
||||||
"\t-l : list all support CAN controller names\n"
|
"\t-l list all support CAN controller names\n"
|
||||||
"\t-b <bitrate> : bit-rate in bits/sec\n"
|
"\t-b <bitrate> bit-rate in bits/sec\n"
|
||||||
"\t-s <samp_pt> : sample-point in one-tenth of a percent\n"
|
"\t-s <samp_pt> sample-point in one-tenth of a percent\n"
|
||||||
"\t or 0 for CIA recommended sample points\n"
|
"\t or 0 for CIA recommended sample points\n"
|
||||||
"\t-c <clock> : real CAN system clock in Hz\n",
|
"\t-c <clock> real CAN system clock in Hz\n",
|
||||||
cmd);
|
cmd);
|
||||||
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void printf_btr_sja1000(struct can_bittiming *bt, bool hdr)
|
static void printf_btr_sja1000(struct can_bittiming *bt, bool hdr)
|
||||||
@@ -444,7 +444,7 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
|
|||||||
unsigned int spt_nominal; /* nominal sample point */
|
unsigned int spt_nominal; /* nominal sample point */
|
||||||
unsigned int best_tseg = 0; /* current best value for tseg */
|
unsigned int best_tseg = 0; /* current best value for tseg */
|
||||||
unsigned int best_brp = 0; /* current best value for brp */
|
unsigned int best_brp = 0; /* current best value for brp */
|
||||||
unsigned int brp, tsegall, tseg, tseg1, tseg2;
|
unsigned int brp, tsegall, tseg, tseg1 = 0, tseg2 = 0;
|
||||||
u64 v64;
|
u64 v64;
|
||||||
|
|
||||||
/* Use CiA recommended sample points */
|
/* Use CiA recommended sample points */
|
||||||
@@ -638,7 +638,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
const struct calc_bittiming_const *btc;
|
const struct calc_bittiming_const *btc;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "b:c:lqs:")) != -1) {
|
while ((opt = getopt(argc, argv, "b:c:lqs:?")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'b':
|
case 'b':
|
||||||
bitrate_nominal = atoi(optarg);
|
bitrate_nominal = atoi(optarg);
|
||||||
@@ -660,14 +660,22 @@ int main(int argc, char *argv[])
|
|||||||
spt_nominal = strtoul(optarg, NULL, 10);
|
spt_nominal = strtoul(optarg, NULL, 10);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case '?':
|
||||||
|
print_usage(basename(argv[0]));
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
print_usage(argv[0]);
|
print_usage(basename(argv[0]));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc > optind + 1)
|
if (argc > optind + 1) {
|
||||||
print_usage(argv[0]);
|
print_usage(argv[0]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
if (argc == optind + 1)
|
if (argc == optind + 1)
|
||||||
name = argv[optind];
|
name = argv[optind];
|
||||||
@@ -677,11 +685,14 @@ int main(int argc, char *argv[])
|
|||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spt_nominal && (spt_nominal >= 1000 || spt_nominal < 100))
|
if (spt_nominal && (spt_nominal >= 1000 || spt_nominal < 100)) {
|
||||||
print_usage(argv[0]);
|
print_usage(argv[0]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(can_calc_consts); i++) {
|
for (i = 0; i < ARRAY_SIZE(can_calc_consts); i++) {
|
||||||
if (name && strcmp(can_calc_consts[i].bittiming_const.name, name))
|
if (name &&
|
||||||
|
strcmp(can_calc_consts[i].bittiming_const.name, name) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
found = true;
|
found = true;
|
||||||
|
|||||||
@@ -0,0 +1,180 @@
|
|||||||
|
# can-j1939 kernel module installation #
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Problem
|
||||||
|
|
||||||
|
You already have **can0** or **vcan0** up and working, **can-utils** downloaded and compiled to **~/can/can-utils** and you can send and receive frames without problems. However, when you want to bring up **can-j1939** you get error like this:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
avra@vm-debian:~/can/can-utils$ sudo modprobe can-j1939
|
||||||
|
modprobe: FATAL: Module can-j1939 not found in directory /lib/modules/5.7.0.0.bpo.2-amd64
|
||||||
|
```
|
||||||
|
|
||||||
|
and also this:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
avra@vm-debian:~/can/can-utils$ testj1939
|
||||||
|
testj1939: socket(j1939): Protocol not supported
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Solution
|
||||||
|
|
||||||
|
Above errors mean that **can-j1939** was not enabled in your kernel and you need to compile it manually. There are several ways to do it. Any Linux kernel since 5.4 has **can-j1939** module, but you will probably want to install fresher version, which leads to downloading kernel sources, enabling **can-j1939** module, recompiling kernel and installing it. I will be using Debian 10.5 x64 (buster testing) virtual machine.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### 1. Download kernel source ####
|
||||||
|
|
||||||
|
We will download Debian patched kernel 5.8. First update your sources
|
||||||
|
|
||||||
|
```
|
||||||
|
avra@vm-debian:~$ sudo apt update
|
||||||
|
```
|
||||||
|
|
||||||
|
and then look at available Debian patched kernel source packages
|
||||||
|
|
||||||
|
```
|
||||||
|
avra@vm-debian:~$ apt-cache search linux-source
|
||||||
|
linux-source-4.19 - Linux kernel source for version 4.19 with Debian patches
|
||||||
|
linux-source - Linux kernel source (meta-package)
|
||||||
|
linux-source-5.4 - Linux kernel source for version 5.4 with Debian patches
|
||||||
|
linux-source-5.5 - Linux kernel source for version 5.5 with Debian patches
|
||||||
|
linux-source-5.6 - Linux kernel source for version 5.6 with Debian patches
|
||||||
|
linux-source-5.7 - Linux kernel source for version 5.7 with Debian patches
|
||||||
|
linux-source-5.8 - Linux kernel source for version 5.8 with Debian patches
|
||||||
|
```
|
||||||
|
|
||||||
|
If kernel 5.8 does not show in your linux-sources list (it shows above in mine since I have already upgraded stock 4.19 kernel to backported 5.7), then you will need to add backports to your sources list. It is best to do it like this
|
||||||
|
|
||||||
|
```
|
||||||
|
echo 'deb http://deb.debian.org/debian buster-backports main contrib' | sudo tee -a /etc/apt/sources.list.d/debian-backports.list
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, or in case you have problems with installation of some packages, or you just want to have everything in a single list, here is what my **/etc/apt/sources.list** looks like (you will need to append at least last line to yours)
|
||||||
|
|
||||||
|
```
|
||||||
|
deb http://security.debian.org/debian-security buster/updates main contrib
|
||||||
|
deb-src http://security.debian.org/debian-security buster/updates main contrib
|
||||||
|
|
||||||
|
deb http://deb.debian.org/debian/ buster main contrib non-free
|
||||||
|
deb-src http://deb.debian.org/debian/ buster main contrib non-free
|
||||||
|
|
||||||
|
deb http://deb.debian.org/debian buster-backports main contrib
|
||||||
|
```
|
||||||
|
|
||||||
|
After adding backports in one way or another, try **sudo apt update** again, and after that **apt-cache search linux-source** should show kernel 5.8 in the list, so you can install it's source package
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt install linux-source-5.8
|
||||||
|
```
|
||||||
|
|
||||||
|
and unpack it
|
||||||
|
```
|
||||||
|
avra@vm-debian:~$ cd /usr/src
|
||||||
|
avra@vm-debian:/usr/src$ sudo tar -xaf linux-source-5.8.tar.xz
|
||||||
|
avra@vm-debian:/usr/src$ cd linux-source-5.8
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### 2. Add can-j1939 module to kernel ####
|
||||||
|
|
||||||
|
First we need some packages for **menuconfig**
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt-get install libncurses5 libncurses5-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
copy and use our old configuration to run **menuconfig**
|
||||||
|
|
||||||
|
```
|
||||||
|
avra@vm-debian:/usr/src/linux-source-5.8$ sudo cp /boot/config-$(uname -r) .config
|
||||||
|
avra@vm-debian:/usr/src/linux-source-5.8$ sudo make menuconfig
|
||||||
|
```
|
||||||
|
|
||||||
|
where we enable SAE J1939 kernel module as shown
|
||||||
|
|
||||||
|
```
|
||||||
|
- Networking Support
|
||||||
|
- Can bus subsystem support
|
||||||
|
- <M> SAE J1939
|
||||||
|
```
|
||||||
|
|
||||||
|
Now edit **/usr/src/linux-source-5.8/.config**, find CONFIG_SYSTEM_TRUSTED_KEYS, change it as following
|
||||||
|
```
|
||||||
|
CONFIG_SYSTEM_TRUSTED_KEYS=""
|
||||||
|
```
|
||||||
|
|
||||||
|
and save the file.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### 3. Compile and install kernel and modules
|
||||||
|
|
||||||
|
We will have to download necessary packages
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt install build-essential libssl-dev libelf-dev bison flex
|
||||||
|
```
|
||||||
|
|
||||||
|
compile kernel (using threads to make it faster)
|
||||||
|
|
||||||
|
```
|
||||||
|
avra@vm-debian:/usr/src/linux-source-5.8$ sudo make -j $(nproc)
|
||||||
|
```
|
||||||
|
|
||||||
|
install
|
||||||
|
|
||||||
|
```
|
||||||
|
avra@vm-debian:/usr/src/linux-source-5.8$ sudo make modules_install
|
||||||
|
avra@vm-debian:/usr/src/linux-source-5.8$ sudo make install
|
||||||
|
```
|
||||||
|
|
||||||
|
and update grub
|
||||||
|
|
||||||
|
```
|
||||||
|
avra@vm-debian:/usr/src/linux-source-5.8$ sudo update-grub
|
||||||
|
avra@vm-debian:/usr/src/linux-source-5.8$ sudo reboot
|
||||||
|
```
|
||||||
|
|
||||||
|
Check if installation is correct with
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo modprobe can-j1939
|
||||||
|
```
|
||||||
|
|
||||||
|
and if you get no error then you can enjoy **can-j1939**. If you get some error then you might check if this alternative command works:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo insmod /lib/modules/5.8.10/kernel/net/can/j1939/can-j1939.ko
|
||||||
|
```
|
||||||
|
|
||||||
|
If it does then all you need to do is
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo depmod -av
|
||||||
|
```
|
||||||
|
|
||||||
|
reboot once, and **modprobe** command from the above should finally work.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### 4. Install headers if needed
|
||||||
|
|
||||||
|
You might have a problem with headers not being updated. To check that open file **/usr/include/linux/can.h** with
|
||||||
|
|
||||||
|
```
|
||||||
|
nano /usr/include/linux/can.h
|
||||||
|
```
|
||||||
|
|
||||||
|
If in the struct **sockaddr_can** you don’t see **j1939**, then header files did not upgrade and you need to do it manually
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo cp /usr/src/linux-source-5.8/include/uapi/linux/can.h /usr/include/linux/can.h
|
||||||
|
sudo cp /usr/src/linux-source-5.8/include/uapi/linux/can/j1939.h /usr/include/linux/can/
|
||||||
|
```
|
||||||
|
|
||||||
|
That is the minimum for compiling some **J1939** C code, but you might want to upgrade other header files as well. That's up to you. Enjoy!
|
||||||
@@ -44,7 +44,7 @@ You should have this output in terminal 1
|
|||||||
40 02300: 01 23
|
40 02300: 01 23
|
||||||
|
|
||||||
This means, from NAME 0, SA 40, PGN 02300 was received,
|
This means, from NAME 0, SA 40, PGN 02300 was received,
|
||||||
with 2 databytes, *01* & *02*.
|
with 2 databytes, *01* & *23*.
|
||||||
|
|
||||||
now emit this CAN message:
|
now emit this CAN message:
|
||||||
|
|
||||||
|
|||||||
+16
-14
@@ -1,6 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
|
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
|
||||||
/*
|
/*
|
||||||
* canbusload.c
|
* canbusload.c - monitor CAN bus load
|
||||||
*
|
*
|
||||||
* Copyright (c) 2002-2008 Volkswagen Group Electronic Research
|
* Copyright (c) 2002-2008 Volkswagen Group Electronic Research
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
@@ -42,21 +42,21 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#include <net/if.h>
|
|
||||||
|
|
||||||
#include <linux/can.h>
|
#include <linux/can.h>
|
||||||
#include <linux/can/raw.h>
|
#include <linux/can/raw.h>
|
||||||
@@ -91,9 +91,11 @@ static char *prg;
|
|||||||
|
|
||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
|
fprintf(stderr, "%s - monitor CAN bus load.\n", prg);
|
||||||
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
|
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
|
||||||
fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg);
|
fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg);
|
||||||
fprintf(stderr, "Options: -t (show current time on the first line)\n");
|
fprintf(stderr, "Options:\n");
|
||||||
|
fprintf(stderr, " -t (show current time on the first line)\n");
|
||||||
fprintf(stderr, " -c (colorize lines)\n");
|
fprintf(stderr, " -c (colorize lines)\n");
|
||||||
fprintf(stderr, " -b (show bargraph in %d%% resolution)\n", PERCENTRES);
|
fprintf(stderr, " -b (show bargraph in %d%% resolution)\n", PERCENTRES);
|
||||||
fprintf(stderr, " -r (redraw the terminal - similar to top)\n");
|
fprintf(stderr, " -r (redraw the terminal - similar to top)\n");
|
||||||
@@ -107,7 +109,7 @@ void print_usage(char *prg)
|
|||||||
fprintf(stderr, "Due to the bitstuffing estimation the calculated busload may exceed 100%%.\n");
|
fprintf(stderr, "Due to the bitstuffing estimation the calculated busload may exceed 100%%.\n");
|
||||||
fprintf(stderr, "For each given interface the data is presented in one line which contains:\n\n");
|
fprintf(stderr, "For each given interface the data is presented in one line which contains:\n\n");
|
||||||
fprintf(stderr, "(interface) (received CAN frames) (used bits total) (used bits for payload)\n");
|
fprintf(stderr, "(interface) (received CAN frames) (used bits total) (used bits for payload)\n");
|
||||||
fprintf(stderr, "\nExample:\n");
|
fprintf(stderr, "\nExamples:\n");
|
||||||
fprintf(stderr, "\nuser$> canbusload can0@100000 can1@500000 can2@500000 can3@500000 -r -t -b -c\n\n");
|
fprintf(stderr, "\nuser$> canbusload can0@100000 can1@500000 can2@500000 can3@500000 -r -t -b -c\n\n");
|
||||||
fprintf(stderr, "%s 2014-02-01 21:13:16 (worst case bitstuffing)\n", prg);
|
fprintf(stderr, "%s 2014-02-01 21:13:16 (worst case bitstuffing)\n", prg);
|
||||||
fprintf(stderr, " can0@100000 805 74491 36656 74%% |XXXXXXXXXXXXXX......|\n");
|
fprintf(stderr, " can0@100000 805 74491 36656 74%% |XXXXXXXXXXXXXX......|\n");
|
||||||
@@ -298,7 +300,7 @@ int main(int argc, char **argv)
|
|||||||
ptr = argv[optind+i];
|
ptr = argv[optind+i];
|
||||||
|
|
||||||
nbytes = strlen(ptr);
|
nbytes = strlen(ptr);
|
||||||
if (nbytes >= IFNAMSIZ+sizeof("@1000000")+1) {
|
if (nbytes >= (int)(IFNAMSIZ+sizeof("@1000000")+1)) {
|
||||||
printf("name of CAN device '%s' is too long!\n", ptr);
|
printf("name of CAN device '%s' is too long!\n", ptr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -322,7 +324,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
nbytes = nptr - ptr; /* interface name is up the first '@' */
|
nbytes = nptr - ptr; /* interface name is up the first '@' */
|
||||||
|
|
||||||
if (nbytes >= IFNAMSIZ) {
|
if (nbytes >= (int)IFNAMSIZ) {
|
||||||
printf("name of CAN device '%s' is too long!\n", ptr);
|
printf("name of CAN device '%s' is too long!\n", ptr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -394,7 +396,7 @@ int main(int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbytes < sizeof(struct can_frame)) {
|
if (nbytes < (int)sizeof(struct can_frame)) {
|
||||||
fprintf(stderr, "read: incomplete CAN frame\n");
|
fprintf(stderr, "read: incomplete CAN frame\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,23 +42,23 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <libgen.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <errno.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#include <net/if.h>
|
|
||||||
|
|
||||||
#include <linux/can.h>
|
#include <linux/can.h>
|
||||||
#include <linux/can/raw.h>
|
#include <linux/can/raw.h>
|
||||||
@@ -116,9 +116,11 @@ static volatile int running = 1;
|
|||||||
|
|
||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
|
fprintf(stderr, "%s - dump CAN bus traffic.\n", prg);
|
||||||
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
|
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
|
||||||
fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg);
|
fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg);
|
||||||
fprintf(stderr, "Options: -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n");
|
fprintf(stderr, "Options:\n");
|
||||||
|
fprintf(stderr, " -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n");
|
||||||
fprintf(stderr, " -H (read hardware timestamps instead of system timestamps)\n");
|
fprintf(stderr, " -H (read hardware timestamps instead of system timestamps)\n");
|
||||||
fprintf(stderr, " -c (increment color mode level)\n");
|
fprintf(stderr, " -c (increment color mode level)\n");
|
||||||
fprintf(stderr, " -i (binary output - may exceed 80 chars/line)\n");
|
fprintf(stderr, " -i (binary output - may exceed 80 chars/line)\n");
|
||||||
@@ -137,22 +139,23 @@ void print_usage(char *prg)
|
|||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "Up to %d CAN interfaces with optional filter sets can be specified\n", MAXSOCK);
|
fprintf(stderr, "Up to %d CAN interfaces with optional filter sets can be specified\n", MAXSOCK);
|
||||||
fprintf(stderr, "on the commandline in the form: <ifname>[,filter]*\n");
|
fprintf(stderr, "on the commandline in the form: <ifname>[,filter]*\n");
|
||||||
fprintf(stderr, "\nComma separated filters can be specified for each given CAN interface:\n");
|
fprintf(stderr, "\nFilters:\n");
|
||||||
fprintf(stderr, " <can_id>:<can_mask> (matches when <received_can_id> & mask == can_id & mask)\n");
|
fprintf(stderr, " Comma separated filters can be specified for each given CAN interface:\n");
|
||||||
fprintf(stderr, " <can_id>~<can_mask> (matches when <received_can_id> & mask != can_id & mask)\n");
|
fprintf(stderr, " <can_id>:<can_mask>\n (matches when <received_can_id> & mask == can_id & mask)\n");
|
||||||
fprintf(stderr, " #<error_mask> (set error frame filter, see include/linux/can/error.h)\n");
|
fprintf(stderr, " <can_id>~<can_mask>\n (matches when <received_can_id> & mask != can_id & mask)\n");
|
||||||
fprintf(stderr, " [j|J] (join the given CAN filters - logical AND semantic)\n");
|
fprintf(stderr, " #<error_mask>\n (set error frame filter, see include/linux/can/error.h)\n");
|
||||||
|
fprintf(stderr, " [j|J]\n (join the given CAN filters - logical AND semantic)\n");
|
||||||
fprintf(stderr, "\nCAN IDs, masks and data content are given and expected in hexadecimal values.\n");
|
fprintf(stderr, "\nCAN IDs, masks and data content are given and expected in hexadecimal values.\n");
|
||||||
fprintf(stderr, "When the can_id is 8 digits long the CAN_EFF_FLAG is set for 29 bit EFF format.\n");
|
fprintf(stderr, "When the can_id is 8 digits long the CAN_EFF_FLAG is set for 29 bit EFF format.\n");
|
||||||
fprintf(stderr, "Without any given filter all data frames are received ('0:0' default filter).\n");
|
fprintf(stderr, "Without any given filter all data frames are received ('0:0' default filter).\n");
|
||||||
fprintf(stderr, "\nUse interface name '%s' to receive from all CAN interfaces.\n", ANYDEV);
|
fprintf(stderr, "\nUse interface name '%s' to receive from all CAN interfaces.\n", ANYDEV);
|
||||||
fprintf(stderr, "\nExamples:\n");
|
fprintf(stderr, "\nExamples:\n");
|
||||||
fprintf(stderr, "%s -c -c -ta can0,123:7FF,400:700,#000000FF can2,400~7F0 can3 can8\n", prg);
|
fprintf(stderr, "%s -c -c -ta can0,123:7FF,400:700,#000000FF can2,400~7F0 can3 can8\n\n", prg);
|
||||||
fprintf(stderr, "%s -l any,0~0,#FFFFFFFF (log only error frames but no(!) data frames)\n", prg);
|
fprintf(stderr, "%s -l any,0~0,#FFFFFFFF\n (log only error frames but no(!) data frames)\n", prg);
|
||||||
fprintf(stderr, "%s -l any,0:0,#FFFFFFFF (log error frames and also all data frames)\n", prg);
|
fprintf(stderr, "%s -l any,0:0,#FFFFFFFF\n (log error frames and also all data frames)\n", prg);
|
||||||
fprintf(stderr, "%s vcan2,12345678:DFFFFFFF (match only for extended CAN ID 12345678)\n", prg);
|
fprintf(stderr, "%s vcan2,12345678:DFFFFFFF\n (match only for extended CAN ID 12345678)\n", prg);
|
||||||
fprintf(stderr, "%s vcan2,123:7FF (matches CAN ID 123 - including EFF and RTR frames)\n", prg);
|
fprintf(stderr, "%s vcan2,123:7FF\n (matches CAN ID 123 - including EFF and RTR frames)\n", prg);
|
||||||
fprintf(stderr, "%s vcan2,123:C00007FF (matches CAN ID 123 - only SFF and non-RTR frames)\n", prg);
|
fprintf(stderr, "%s vcan2,123:C00007FF\n (matches CAN ID 123 - only SFF and non-RTR frames)\n", prg);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,7 +201,7 @@ int idx2dindex(int ifidx, int socket) {
|
|||||||
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
|
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
|
||||||
perror("SIOCGIFNAME");
|
perror("SIOCGIFNAME");
|
||||||
|
|
||||||
if (max_devname_len < strlen(ifr.ifr_name))
|
if (max_devname_len < (int)strlen(ifr.ifr_name))
|
||||||
max_devname_len = strlen(ifr.ifr_name);
|
max_devname_len = strlen(ifr.ifr_name);
|
||||||
|
|
||||||
strcpy(devname[i], ifr.ifr_name);
|
strcpy(devname[i], ifr.ifr_name);
|
||||||
@@ -414,7 +417,7 @@ int main(int argc, char **argv)
|
|||||||
printf("using interface name '%s'.\n", ifr.ifr_name);
|
printf("using interface name '%s'.\n", ifr.ifr_name);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (strcmp(ANYDEV, ifr.ifr_name)) {
|
if (strcmp(ANYDEV, ifr.ifr_name) != 0) {
|
||||||
if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
|
if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
|
||||||
perror("SIOCGIFINDEX");
|
perror("SIOCGIFINDEX");
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -625,6 +628,7 @@ int main(int argc, char **argv)
|
|||||||
if (FD_ISSET(s[i], &rdfs)) {
|
if (FD_ISSET(s[i], &rdfs)) {
|
||||||
|
|
||||||
int idx;
|
int idx;
|
||||||
|
char *extra_info = "";
|
||||||
|
|
||||||
/* these settings may be modified by recvmsg() */
|
/* these settings may be modified by recvmsg() */
|
||||||
iov.iov_len = sizeof(frame);
|
iov.iov_len = sizeof(frame);
|
||||||
@@ -698,14 +702,22 @@ int main(int argc, char **argv)
|
|||||||
if (frame.can_id & CAN_EFF_FLAG)
|
if (frame.can_id & CAN_EFF_FLAG)
|
||||||
view |= CANLIB_VIEW_INDENT_SFF;
|
view |= CANLIB_VIEW_INDENT_SFF;
|
||||||
|
|
||||||
|
if (extra_msg_info) {
|
||||||
|
if (msg.msg_flags & MSG_DONTROUTE)
|
||||||
|
extra_info = " T";
|
||||||
|
else
|
||||||
|
extra_info = " R";
|
||||||
|
}
|
||||||
|
|
||||||
if (log) {
|
if (log) {
|
||||||
char buf[CL_CFSZ]; /* max length */
|
char buf[CL_CFSZ]; /* max length */
|
||||||
|
|
||||||
/* log CAN frame with absolute timestamp & device */
|
/* log CAN frame with absolute timestamp & device */
|
||||||
sprint_canframe(buf, &frame, 0, maxdlen);
|
sprint_canframe(buf, &frame, 0, maxdlen);
|
||||||
fprintf(logfile, "(%010ld.%06ld) %*s %s\n",
|
fprintf(logfile, "(%010lu.%06lu) %*s %s%s\n",
|
||||||
tv.tv_sec, tv.tv_usec,
|
tv.tv_sec, tv.tv_usec,
|
||||||
max_devname_len, devname[idx], buf);
|
max_devname_len, devname[idx], buf,
|
||||||
|
extra_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((logfrmt) && (silent == SILENT_OFF)){
|
if ((logfrmt) && (silent == SILENT_OFF)){
|
||||||
@@ -713,9 +725,10 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
/* print CAN frame in log file style to stdout */
|
/* print CAN frame in log file style to stdout */
|
||||||
sprint_canframe(buf, &frame, 0, maxdlen);
|
sprint_canframe(buf, &frame, 0, maxdlen);
|
||||||
printf("(%010ld.%06ld) %*s %s\n",
|
printf("(%010lu.%06lu) %*s %s%s\n",
|
||||||
tv.tv_sec, tv.tv_usec,
|
tv.tv_sec, tv.tv_usec,
|
||||||
max_devname_len, devname[idx], buf);
|
max_devname_len, devname[idx], buf,
|
||||||
|
extra_info);
|
||||||
goto out_fflush; /* no other output to stdout */
|
goto out_fflush; /* no other output to stdout */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -732,7 +745,7 @@ int main(int argc, char **argv)
|
|||||||
switch (timestamp) {
|
switch (timestamp) {
|
||||||
|
|
||||||
case 'a': /* absolute with timestamp */
|
case 'a': /* absolute with timestamp */
|
||||||
printf("(%010ld.%06ld) ", tv.tv_sec, tv.tv_usec);
|
printf("(%010lu.%06lu) ", tv.tv_sec, tv.tv_usec);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'A': /* absolute with date */
|
case 'A': /* absolute with date */
|
||||||
@@ -742,7 +755,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
tm = *localtime(&tv.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);
|
||||||
printf("(%s.%06ld) ", timestring, tv.tv_usec);
|
printf("(%s.%06lu) ", timestring, tv.tv_usec);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -759,7 +772,7 @@ int main(int argc, char **argv)
|
|||||||
diff.tv_sec--, diff.tv_usec += 1000000;
|
diff.tv_sec--, diff.tv_usec += 1000000;
|
||||||
if (diff.tv_sec < 0)
|
if (diff.tv_sec < 0)
|
||||||
diff.tv_sec = diff.tv_usec = 0;
|
diff.tv_sec = diff.tv_usec = 0;
|
||||||
printf("(%03ld.%06ld) ", diff.tv_sec, diff.tv_usec);
|
printf("(%03lu.%06lu) ", diff.tv_sec, diff.tv_usec);
|
||||||
|
|
||||||
if (timestamp == 'd')
|
if (timestamp == 'd')
|
||||||
last_tv = tv; /* update for delta calculation */
|
last_tv = tv; /* update for delta calculation */
|
||||||
|
|||||||
+119
-56
@@ -17,23 +17,24 @@
|
|||||||
* Send feedback to <linux-can@vger.kernel.org>
|
* Send feedback to <linux-can@vger.kernel.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <sched.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <libgen.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sched.h>
|
#include <unistd.h>
|
||||||
#include <limits.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <linux/can.h>
|
#include <linux/can.h>
|
||||||
#include <linux/can/raw.h>
|
#include <linux/can/raw.h>
|
||||||
@@ -48,31 +49,37 @@ static int verbose;
|
|||||||
static int sockfd;
|
static int sockfd;
|
||||||
static int test_loops;
|
static int test_loops;
|
||||||
static int exit_sig;
|
static int exit_sig;
|
||||||
|
static int inflight_count = CAN_MSG_COUNT;
|
||||||
|
|
||||||
static void print_usage(char *prg)
|
static void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
|
"%s - Full-duplex test program (DUT and host part).\n"
|
||||||
"Usage: %s [options] <can-interface>\n"
|
"Usage: %s [options] <can-interface>\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Options: -v (low verbosity)\n"
|
"Options:\n"
|
||||||
|
" -v (low verbosity)\n"
|
||||||
" -vv (high verbosity)\n"
|
" -vv (high verbosity)\n"
|
||||||
" -g (generate messages)\n"
|
" -g (generate messages)\n"
|
||||||
" -l COUNT (test loop count)\n"
|
" -l COUNT (test loop count)\n"
|
||||||
|
" -f COUNT (number of frames in flight, default: %d)\n"
|
||||||
"\n"
|
"\n"
|
||||||
"With the option '-g' CAN messages are generated and checked\n"
|
"With the option '-g' CAN messages are generated and checked\n"
|
||||||
"on <can-interface>, otherwise all messages received on the\n"
|
"on <can-interface>, otherwise all messages received on the\n"
|
||||||
"<can-interface> are sent back incrementing the CAN id and\n"
|
"<can-interface> are sent back incrementing the CAN id and\n"
|
||||||
"all data bytes. The program can be aborted with ^C.\n"
|
"all data bytes. The program can be aborted with ^C.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Example:\n"
|
"Examples:\n"
|
||||||
"\ton DUT : %s -v can0\n"
|
"\ton DUT:\n"
|
||||||
"\ton Host: %s -g -v can2\n",
|
"%s -v can0\n"
|
||||||
prg, prg, prg);
|
"\ton Host:\n"
|
||||||
|
"%s -g -v can2\n",
|
||||||
|
prg, prg, CAN_MSG_COUNT, prg, prg);
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_frame(struct can_frame *frame, int inc)
|
static void print_frame(const struct can_frame *frame, int inc)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -82,12 +89,12 @@ static void print_frame(struct can_frame *frame, int inc)
|
|||||||
} else {
|
} else {
|
||||||
printf("[%d]", frame->can_dlc);
|
printf("[%d]", frame->can_dlc);
|
||||||
for (i = 0; i < frame->can_dlc; i++)
|
for (i = 0; i < frame->can_dlc; i++)
|
||||||
printf(" %02x", frame->data[i] + inc);
|
printf(" %02x", (uint8_t)(frame->data[i] + inc));
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_compare(struct can_frame *exp, struct can_frame *rec, int inc)
|
static void print_compare(const struct can_frame *exp, const struct can_frame *rec, int inc)
|
||||||
{
|
{
|
||||||
printf("expected: ");
|
printf("expected: ");
|
||||||
print_frame(exp, inc);
|
print_frame(exp, inc);
|
||||||
@@ -109,8 +116,8 @@ static void compare_frame(struct can_frame *exp, struct can_frame *rec, int inc)
|
|||||||
running = 0;
|
running = 0;
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < rec->can_dlc; i++) {
|
for (i = 0; i < rec->can_dlc; i++) {
|
||||||
if (rec->data[i] != ((exp->data[i] + inc) & 0xff)) {
|
if (rec->data[i] != (uint8_t)(exp->data[i] + inc)) {
|
||||||
printf("Databyte %x mismatch !\n", i);
|
printf("Databyte %x mismatch!\n", i);
|
||||||
print_compare(exp,
|
print_compare(exp,
|
||||||
rec, inc);
|
rec, inc);
|
||||||
running = 0;
|
running = 0;
|
||||||
@@ -174,29 +181,63 @@ static int send_frame(struct can_frame *frame)
|
|||||||
|
|
||||||
while ((ret = send(sockfd, frame, sizeof(*frame), 0))
|
while ((ret = send(sockfd, frame, sizeof(*frame), 0))
|
||||||
!= sizeof(*frame)) {
|
!= sizeof(*frame)) {
|
||||||
if (ret < 0) {
|
if (ret >= 0) {
|
||||||
|
fprintf(stderr, "send returned %d", ret);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (errno != ENOBUFS) {
|
if (errno != ENOBUFS) {
|
||||||
perror("send failed");
|
perror("send failed");
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
}
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
printf("N");
|
printf("N");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
fprintf(stderr, "send returned %d", ret);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int check_frame(const struct can_frame *frame)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (frame->can_id != CAN_MSG_ID) {
|
||||||
|
printf("unexpected Message ID 0x%04x!\n", frame->can_id);
|
||||||
|
err = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frame->can_dlc != CAN_MSG_LEN) {
|
||||||
|
printf("unexpected Message length %d!\n", frame->can_dlc);
|
||||||
|
err = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 1; i < frame->can_dlc; i++) {
|
||||||
|
if (frame->data[i] != (uint8_t)(frame->data[i-1] + 1)) {
|
||||||
|
printf("Frame inconsistent!\n");
|
||||||
|
print_frame(frame, 0);
|
||||||
|
err = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void inc_frame(struct can_frame *frame)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
frame->can_id++;
|
||||||
|
for (i = 0; i < frame->can_dlc; i++)
|
||||||
|
frame->data[i]++;
|
||||||
|
}
|
||||||
|
|
||||||
static int can_echo_dut(void)
|
static int can_echo_dut(void)
|
||||||
{
|
{
|
||||||
unsigned int frame_count = 0;
|
unsigned int frame_count = 0;
|
||||||
struct can_frame frame;
|
struct can_frame frame;
|
||||||
int i;
|
|
||||||
|
|
||||||
while (running) {
|
while (running) {
|
||||||
if (recv_frame(&frame))
|
if (recv_frame(&frame))
|
||||||
@@ -205,19 +246,11 @@ static int can_echo_dut(void)
|
|||||||
if (verbose == 1) {
|
if (verbose == 1) {
|
||||||
echo_progress(frame.data[0]);
|
echo_progress(frame.data[0]);
|
||||||
} else if (verbose > 1) {
|
} else if (verbose > 1) {
|
||||||
printf("%04x: ", frame.can_id);
|
print_frame(&frame, 0);
|
||||||
if (frame.can_id & CAN_RTR_FLAG) {
|
|
||||||
printf("remote request");
|
|
||||||
} else {
|
|
||||||
printf("[%d]", frame.can_dlc);
|
|
||||||
for (i = 0; i < frame.can_dlc; i++)
|
|
||||||
printf(" %02x", frame.data[i]);
|
|
||||||
}
|
}
|
||||||
printf("\n");
|
|
||||||
}
|
check_frame(&frame);
|
||||||
frame.can_id++;
|
inc_frame(&frame);
|
||||||
for (i = 0; i < frame.can_dlc; i++)
|
|
||||||
frame.data[i]++;
|
|
||||||
if (send_frame(&frame))
|
if (send_frame(&frame))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@@ -236,15 +269,26 @@ static int can_echo_dut(void)
|
|||||||
|
|
||||||
static int can_echo_gen(void)
|
static int can_echo_gen(void)
|
||||||
{
|
{
|
||||||
struct can_frame tx_frames[CAN_MSG_COUNT];
|
struct can_frame *tx_frames;
|
||||||
int recv_tx[CAN_MSG_COUNT];
|
int *recv_tx;
|
||||||
struct can_frame rx_frame;
|
struct can_frame rx_frame;
|
||||||
unsigned char counter = 0;
|
unsigned char counter = 0;
|
||||||
int send_pos = 0, recv_rx_pos = 0, recv_tx_pos = 0, unprocessed = 0, loops = 0;
|
int send_pos = 0, recv_rx_pos = 0, recv_tx_pos = 0, unprocessed = 0, loops = 0;
|
||||||
|
int err = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
tx_frames = calloc(inflight_count, sizeof(* tx_frames));
|
||||||
|
if (!tx_frames)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
recv_tx = calloc(inflight_count, sizeof(* recv_tx));
|
||||||
|
if (!recv_tx) {
|
||||||
|
err = -1;
|
||||||
|
goto out_free_tx_frames;
|
||||||
|
}
|
||||||
|
|
||||||
while (running) {
|
while (running) {
|
||||||
if (unprocessed < CAN_MSG_COUNT) {
|
if (unprocessed < inflight_count) {
|
||||||
/* still send messages */
|
/* still send messages */
|
||||||
tx_frames[send_pos].can_dlc = CAN_MSG_LEN;
|
tx_frames[send_pos].can_dlc = CAN_MSG_LEN;
|
||||||
tx_frames[send_pos].can_id = CAN_MSG_ID;
|
tx_frames[send_pos].can_id = CAN_MSG_ID;
|
||||||
@@ -252,11 +296,13 @@ static int can_echo_gen(void)
|
|||||||
|
|
||||||
for (i = 0; i < CAN_MSG_LEN; i++)
|
for (i = 0; i < CAN_MSG_LEN; i++)
|
||||||
tx_frames[send_pos].data[i] = counter + i;
|
tx_frames[send_pos].data[i] = counter + i;
|
||||||
if (send_frame(&tx_frames[send_pos]))
|
if (send_frame(&tx_frames[send_pos])) {
|
||||||
return -1;
|
err = -1;
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
|
|
||||||
send_pos++;
|
send_pos++;
|
||||||
if (send_pos == CAN_MSG_COUNT)
|
if (send_pos == inflight_count)
|
||||||
send_pos = 0;
|
send_pos = 0;
|
||||||
unprocessed++;
|
unprocessed++;
|
||||||
if (verbose == 1)
|
if (verbose == 1)
|
||||||
@@ -268,8 +314,10 @@ static int can_echo_gen(void)
|
|||||||
else
|
else
|
||||||
millisleep(1);
|
millisleep(1);
|
||||||
} else {
|
} else {
|
||||||
if (recv_frame(&rx_frame))
|
if (recv_frame(&rx_frame)) {
|
||||||
return -1;
|
err = -1;
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
|
|
||||||
if (verbose > 1)
|
if (verbose > 1)
|
||||||
print_frame(&rx_frame, 0);
|
print_frame(&rx_frame, 0);
|
||||||
@@ -279,20 +327,21 @@ static int can_echo_gen(void)
|
|||||||
compare_frame(&tx_frames[recv_tx_pos], &rx_frame, 0);
|
compare_frame(&tx_frames[recv_tx_pos], &rx_frame, 0);
|
||||||
recv_tx[recv_tx_pos] = 1;
|
recv_tx[recv_tx_pos] = 1;
|
||||||
recv_tx_pos++;
|
recv_tx_pos++;
|
||||||
if (recv_tx_pos == CAN_MSG_COUNT)
|
if (recv_tx_pos == inflight_count)
|
||||||
recv_tx_pos = 0;
|
recv_tx_pos = 0;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
if (!recv_tx[recv_rx_pos]) {
|
if (!recv_tx[recv_rx_pos]) {
|
||||||
printf("RX before TX!\n");
|
printf("RX before TX!\n");
|
||||||
|
print_frame(&rx_frame, 0);
|
||||||
running = 0;
|
running = 0;
|
||||||
}
|
}
|
||||||
/* compare with expected */
|
/* compare with expected */
|
||||||
compare_frame(&tx_frames[recv_rx_pos], &rx_frame, 1);
|
compare_frame(&tx_frames[recv_rx_pos], &rx_frame, 1);
|
||||||
recv_rx_pos++;
|
recv_rx_pos++;
|
||||||
if (recv_rx_pos == CAN_MSG_COUNT)
|
if (recv_rx_pos == inflight_count)
|
||||||
recv_rx_pos = 0;
|
recv_rx_pos = 0;
|
||||||
}
|
|
||||||
|
|
||||||
loops++;
|
loops++;
|
||||||
if (test_loops && loops >= test_loops)
|
if (test_loops && loops >= test_loops)
|
||||||
@@ -304,7 +353,12 @@ static int can_echo_gen(void)
|
|||||||
|
|
||||||
printf("\nTest messages sent and received: %d\n", loops);
|
printf("\nTest messages sent and received: %d\n", loops);
|
||||||
|
|
||||||
return 0;
|
out_free:
|
||||||
|
free(recv_tx);
|
||||||
|
out_free_tx_frames:
|
||||||
|
free(tx_frames);
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
@@ -320,20 +374,24 @@ int main(int argc, char *argv[])
|
|||||||
signal(SIGHUP, signal_handler);
|
signal(SIGHUP, signal_handler);
|
||||||
signal(SIGINT, signal_handler);
|
signal(SIGINT, signal_handler);
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "gl:v")) != -1) {
|
while ((opt = getopt(argc, argv, "f:gl:v?")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'v':
|
case 'v':
|
||||||
verbose++;
|
verbose++;
|
||||||
break;
|
break;
|
||||||
|
case 'f':
|
||||||
|
inflight_count = atoi(optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
test_loops = atoi(optarg);;
|
test_loops = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'g':
|
case 'g':
|
||||||
echo_gen = 1;
|
echo_gen = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case '?':
|
||||||
default:
|
default:
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
break;
|
break;
|
||||||
@@ -362,6 +420,11 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
addr.can_family = family;
|
addr.can_family = family;
|
||||||
addr.can_ifindex = if_nametoindex(intf_name);
|
addr.can_ifindex = if_nametoindex(intf_name);
|
||||||
|
if (!addr.can_ifindex) {
|
||||||
|
perror("if_nametoindex");
|
||||||
|
close(sockfd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||||
perror("bind");
|
perror("bind");
|
||||||
|
|||||||
+7
-6
@@ -44,13 +44,14 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "canframelen.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "canframelen.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Functions and types for CRC checks.
|
* Functions and types for CRC checks.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
|
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
|
||||||
/*
|
/*
|
||||||
* cangen.c - CAN frames generator for testing purposes
|
* cangen.c - CAN frames generator
|
||||||
*
|
*
|
||||||
* Copyright (c) 2002-2007 Volkswagen Group Electronic Research
|
* Copyright (c) 2002-2007 Volkswagen Group Electronic Research
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
@@ -42,30 +42,32 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <poll.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <libgen.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <errno.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#include <net/if.h>
|
|
||||||
|
|
||||||
#include <linux/can.h>
|
#include <linux/can.h>
|
||||||
#include <linux/can/raw.h>
|
#include <linux/can/raw.h>
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
|
|
||||||
#define DEFAULT_GAP 200 /* ms */
|
#define DEFAULT_GAP 200 /* ms */
|
||||||
|
#define DEFAULT_BURST_COUNT 1
|
||||||
|
|
||||||
#define MODE_RANDOM 0
|
#define MODE_RANDOM 0
|
||||||
#define MODE_INCREMENT 1
|
#define MODE_INCREMENT 1
|
||||||
@@ -78,17 +80,20 @@ static unsigned long long enobufs_count;
|
|||||||
|
|
||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "\n%s: generate CAN frames\n\n", prg);
|
fprintf(stderr, "%s - CAN frames generator.\n\n", prg);
|
||||||
fprintf(stderr, "Usage: %s [options] <CAN interface>\n", prg);
|
fprintf(stderr, "Usage: %s [options] <CAN interface>\n", prg);
|
||||||
fprintf(stderr, "Options: -g <ms> (gap in milli seconds "
|
fprintf(stderr, "Options:\n");
|
||||||
|
fprintf(stderr, " -g <ms> (gap in milli seconds "
|
||||||
"- default: %d ms)\n", DEFAULT_GAP);
|
"- default: %d ms)\n", DEFAULT_GAP);
|
||||||
fprintf(stderr, " -e (generate extended frame mode "
|
fprintf(stderr, " -e (generate extended frame mode "
|
||||||
"(EFF) CAN frames)\n");
|
"(EFF) CAN frames)\n");
|
||||||
fprintf(stderr, " -f (generate CAN FD CAN frames)\n");
|
fprintf(stderr, " -f (generate CAN FD CAN frames)\n");
|
||||||
fprintf(stderr, " -b (generate CAN FD CAN frames"
|
fprintf(stderr, " -b (generate CAN FD CAN frames"
|
||||||
" with bitrate switch (BRS))\n");
|
" with bitrate switch (BRS))\n");
|
||||||
|
fprintf(stderr, " -E (generate CAN FD CAN frames"
|
||||||
|
" with error state (ESI))\n");
|
||||||
fprintf(stderr, " -R (send RTR frame)\n");
|
fprintf(stderr, " -R (send RTR frame)\n");
|
||||||
fprintf(stderr, " -m (mix -e -f -b -R frames)\n");
|
fprintf(stderr, " -m (mix -e -f -b -E -R frames)\n");
|
||||||
fprintf(stderr, " -I <mode> (CAN ID"
|
fprintf(stderr, " -I <mode> (CAN ID"
|
||||||
" generation mode - see below)\n");
|
" generation mode - see below)\n");
|
||||||
fprintf(stderr, " -L <mode> (CAN data length code (dlc)"
|
fprintf(stderr, " -L <mode> (CAN data length code (dlc)"
|
||||||
@@ -103,28 +108,30 @@ void print_usage(char *prg)
|
|||||||
" write() syscalls)\n");
|
" write() syscalls)\n");
|
||||||
fprintf(stderr, " -x (disable local loopback of "
|
fprintf(stderr, " -x (disable local loopback of "
|
||||||
"generated CAN frames)\n");
|
"generated CAN frames)\n");
|
||||||
|
fprintf(stderr, " -c (number of messages to send in burst, "
|
||||||
|
"default 1)\n");
|
||||||
fprintf(stderr, " -v (increment verbose level for "
|
fprintf(stderr, " -v (increment verbose level for "
|
||||||
"printing sent CAN frames)\n\n");
|
"printing sent CAN frames)\n\n");
|
||||||
fprintf(stderr, "Generation modes:\n");
|
fprintf(stderr, "Generation modes:\n");
|
||||||
fprintf(stderr, "'r' => random values (default)\n");
|
fprintf(stderr, " 'r' => random values (default)\n");
|
||||||
fprintf(stderr, "'i' => increment values\n");
|
fprintf(stderr, " 'i' => increment values\n");
|
||||||
fprintf(stderr, "<hexvalue> => fix value using <hexvalue>\n\n");
|
fprintf(stderr, " <hexvalue> => fix value using <hexvalue>\n\n");
|
||||||
fprintf(stderr, "When incrementing the CAN data the data length code "
|
fprintf(stderr, "When incrementing the CAN data the data length code "
|
||||||
"minimum is set to 1.\n");
|
"minimum is set to 1.\n");
|
||||||
fprintf(stderr, "CAN IDs and data content are given and expected in hexadecimal values.\n\n");
|
fprintf(stderr, "CAN IDs and data content are given and expected in hexadecimal values.\n\n");
|
||||||
fprintf(stderr, "Examples:\n");
|
fprintf(stderr, "Examples:\n");
|
||||||
fprintf(stderr, "%s vcan0 -g 4 -I 42A -L 1 -D i -v -v ", prg);
|
fprintf(stderr, "%s vcan0 -g 4 -I 42A -L 1 -D i -v -v\n", prg);
|
||||||
fprintf(stderr, "(fixed CAN ID and length, inc. data)\n");
|
fprintf(stderr, "\t(fixed CAN ID and length, inc. data)\n");
|
||||||
fprintf(stderr, "%s vcan0 -e -L i -v -v -v ", prg);
|
fprintf(stderr, "%s vcan0 -e -L i -v -v -v\n", prg);
|
||||||
fprintf(stderr, "(generate EFF frames, incr. length)\n");
|
fprintf(stderr, "\t(generate EFF frames, incr. length)\n");
|
||||||
fprintf(stderr, "%s vcan0 -D 11223344DEADBEEF -L 8 ", prg);
|
fprintf(stderr, "%s vcan0 -D 11223344DEADBEEF -L 8\n", prg);
|
||||||
fprintf(stderr, "(fixed CAN data payload and length)\n");
|
fprintf(stderr, "\t(fixed CAN data payload and length)\n");
|
||||||
fprintf(stderr, "%s vcan0 -g 0 -i -x ", prg);
|
fprintf(stderr, "%s vcan0 -g 0 -i -x\n", prg);
|
||||||
fprintf(stderr, "(full load test ignoring -ENOBUFS)\n");
|
fprintf(stderr, "\t(full load test ignoring -ENOBUFS)\n");
|
||||||
fprintf(stderr, "%s vcan0 -g 0 -p 10 -x ", prg);
|
fprintf(stderr, "%s vcan0 -g 0 -p 10 -x\n", prg);
|
||||||
fprintf(stderr, "(full load test with polling, 10ms timeout)\n");
|
fprintf(stderr, "\t(full load test with polling, 10ms timeout)\n");
|
||||||
fprintf(stderr, "%s vcan0 ", prg);
|
fprintf(stderr, "%s vcan0\n", prg);
|
||||||
fprintf(stderr, "(my favourite default :)\n\n");
|
fprintf(stderr, "\t(my favourite default :)\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void sigterm(int signo)
|
void sigterm(int signo)
|
||||||
@@ -135,11 +142,13 @@ void sigterm(int signo)
|
|||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
double gap = DEFAULT_GAP;
|
double gap = DEFAULT_GAP;
|
||||||
|
unsigned long burst_count = DEFAULT_BURST_COUNT;
|
||||||
unsigned long polltimeout = 0;
|
unsigned long polltimeout = 0;
|
||||||
unsigned char ignore_enobufs = 0;
|
unsigned char ignore_enobufs = 0;
|
||||||
unsigned char extended = 0;
|
unsigned char extended = 0;
|
||||||
unsigned char canfd = 0;
|
unsigned char canfd = 0;
|
||||||
unsigned char brs = 0;
|
unsigned char brs = 0;
|
||||||
|
unsigned char esi = 0;
|
||||||
unsigned char mix = 0;
|
unsigned char mix = 0;
|
||||||
unsigned char id_mode = MODE_RANDOM;
|
unsigned char id_mode = MODE_RANDOM;
|
||||||
unsigned char data_mode = MODE_RANDOM;
|
unsigned char data_mode = MODE_RANDOM;
|
||||||
@@ -148,6 +157,7 @@ int main(int argc, char **argv)
|
|||||||
unsigned char verbose = 0;
|
unsigned char verbose = 0;
|
||||||
unsigned char rtr_frame = 0;
|
unsigned char rtr_frame = 0;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
unsigned long burst_sent_count = 0;
|
||||||
int mtu, maxdlen;
|
int mtu, maxdlen;
|
||||||
uint64_t incdata = 0;
|
uint64_t incdata = 0;
|
||||||
int incdlc = 0;
|
int incdlc = 0;
|
||||||
@@ -175,7 +185,7 @@ int main(int argc, char **argv)
|
|||||||
signal(SIGHUP, sigterm);
|
signal(SIGHUP, sigterm);
|
||||||
signal(SIGINT, sigterm);
|
signal(SIGINT, sigterm);
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "ig:ebfmI:L:D:xp:n:vRh?")) != -1) {
|
while ((opt = getopt(argc, argv, "ig:ebEfmI:L:D:xp:n:c:vRh?")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
@@ -199,6 +209,11 @@ int main(int argc, char **argv)
|
|||||||
canfd = 1;
|
canfd = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'E':
|
||||||
|
esi = 1; /* error state indicator implies CAN FD */
|
||||||
|
canfd = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'm':
|
case 'm':
|
||||||
mix = 1;
|
mix = 1;
|
||||||
canfd = 1; /* to switch the socket into CAN FD mode */
|
canfd = 1; /* to switch the socket into CAN FD mode */
|
||||||
@@ -240,6 +255,10 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
burst_count = strtoul(optarg, NULL, 10);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'v':
|
case 'v':
|
||||||
verbose++;
|
verbose++;
|
||||||
break;
|
break;
|
||||||
@@ -279,7 +298,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ts.tv_sec = gap / 1000;
|
ts.tv_sec = gap / 1000;
|
||||||
ts.tv_nsec = (long)(((long long)(gap * 1000000)) % 1000000000ll);
|
ts.tv_nsec = (long)(((long long)(gap * 1000000)) % 1000000000LL);
|
||||||
|
|
||||||
/* recognize obviously missing commandline option */
|
/* recognize obviously missing commandline option */
|
||||||
if (id_mode == MODE_FIX && frame.can_id > 0x7FF && !extended) {
|
if (id_mode == MODE_FIX && frame.can_id > 0x7FF && !extended) {
|
||||||
@@ -369,6 +388,8 @@ int main(int argc, char **argv)
|
|||||||
maxdlen = CANFD_MAX_DLEN;
|
maxdlen = CANFD_MAX_DLEN;
|
||||||
if (brs)
|
if (brs)
|
||||||
frame.flags |= CANFD_BRS;
|
frame.flags |= CANFD_BRS;
|
||||||
|
if (esi)
|
||||||
|
frame.flags |= CANFD_ESI;
|
||||||
} else {
|
} else {
|
||||||
mtu = CAN_MTU;
|
mtu = CAN_MTU;
|
||||||
maxdlen = CAN_MAX_DLEN;
|
maxdlen = CAN_MAX_DLEN;
|
||||||
@@ -448,7 +469,7 @@ resend:
|
|||||||
if (poll(&fds, 1, polltimeout) < 0) {
|
if (poll(&fds, 1, polltimeout) < 0) {
|
||||||
perror("poll");
|
perror("poll");
|
||||||
return 1;
|
return 1;
|
||||||
} else
|
}
|
||||||
goto resend;
|
goto resend;
|
||||||
} else
|
} else
|
||||||
enobufs_count++;
|
enobufs_count++;
|
||||||
@@ -458,10 +479,14 @@ resend:
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gap) /* gap == 0 => performance test :-] */
|
burst_sent_count++;
|
||||||
|
if (gap && burst_sent_count >= burst_count) /* gap == 0 => performance test :-] */
|
||||||
if (nanosleep(&ts, NULL))
|
if (nanosleep(&ts, NULL))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
if (burst_sent_count >= burst_count)
|
||||||
|
burst_sent_count = 0;
|
||||||
|
|
||||||
if (id_mode == MODE_INCREMENT)
|
if (id_mode == MODE_INCREMENT)
|
||||||
frame.can_id++;
|
frame.can_id++;
|
||||||
|
|
||||||
@@ -490,8 +515,10 @@ resend:
|
|||||||
i = random();
|
i = random();
|
||||||
extended = i&1;
|
extended = i&1;
|
||||||
canfd = i&2;
|
canfd = i&2;
|
||||||
if (canfd)
|
if (canfd) {
|
||||||
brs = i&4;
|
brs = i&4;
|
||||||
|
esi = i&8;
|
||||||
|
}
|
||||||
rtr_frame = ((i&24) == 24); /* reduce RTR frames to 1/4 */
|
rtr_frame = ((i&24) == 24); /* reduce RTR frames to 1/4 */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,17 +42,17 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <libgen.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/socket.h>
|
#include <libgen.h>
|
||||||
#include <net/if.h>
|
#include <linux/can/gw.h>
|
||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
#include <linux/rtnetlink.h>
|
#include <linux/rtnetlink.h>
|
||||||
#include <linux/can/gw.h>
|
#include <net/if.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
UNSPEC,
|
UNSPEC,
|
||||||
@@ -80,7 +80,7 @@ struct fdmodattr {
|
|||||||
|
|
||||||
/* some netlink helpers stolen from iproute2 package */
|
/* some netlink helpers stolen from iproute2 package */
|
||||||
#define NLMSG_TAIL(nmsg) \
|
#define NLMSG_TAIL(nmsg) \
|
||||||
((struct rtattr *)(((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
|
((struct rtattr *)(((char *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
|
||||||
|
|
||||||
int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
|
int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
|
||||||
int alen)
|
int alen)
|
||||||
@@ -88,7 +88,7 @@ int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
|
|||||||
int len = RTA_LENGTH(alen);
|
int len = RTA_LENGTH(alen);
|
||||||
struct rtattr *rta;
|
struct rtattr *rta;
|
||||||
|
|
||||||
if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
|
if ((int)(NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len)) > maxlen) {
|
||||||
fprintf(stderr, "addattr_l: message exceeded bound of %d\n",
|
fprintf(stderr, "addattr_l: message exceeded bound of %d\n",
|
||||||
maxlen);
|
maxlen);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -222,14 +222,18 @@ void print_cs_crc8(struct cgw_csum_crc8 *cs_crc8)
|
|||||||
|
|
||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
|
fprintf(stderr, "%s - manage PF_CAN netlink gateway.\n", prg);
|
||||||
fprintf(stderr, "\nUsage: %s [options]\n\n", prg);
|
fprintf(stderr, "\nUsage: %s [options]\n\n", prg);
|
||||||
fprintf(stderr, "Commands: -A (add a new rule)\n");
|
fprintf(stderr, "Commands:\n");
|
||||||
|
fprintf(stderr, " -A (add a new rule)\n");
|
||||||
fprintf(stderr, " -D (delete a rule)\n");
|
fprintf(stderr, " -D (delete a rule)\n");
|
||||||
fprintf(stderr, " -F (flush / delete all rules)\n");
|
fprintf(stderr, " -F (flush / delete all rules)\n");
|
||||||
fprintf(stderr, " -L (list all rules)\n");
|
fprintf(stderr, " -L (list all rules)\n");
|
||||||
fprintf(stderr, "Mandatory: -s <src_dev> (source netdevice)\n");
|
fprintf(stderr, "Mandatory:\n");
|
||||||
|
fprintf(stderr, " -s <src_dev> (source netdevice)\n");
|
||||||
fprintf(stderr, " -d <dst_dev> (destination netdevice)\n");
|
fprintf(stderr, " -d <dst_dev> (destination netdevice)\n");
|
||||||
fprintf(stderr, "Options: -X (this is a CAN FD rule)\n");
|
fprintf(stderr, "Options:\n");
|
||||||
|
fprintf(stderr, " -X (this is a CAN FD rule)\n");
|
||||||
fprintf(stderr, " -t (preserve src_dev rx timestamp)\n");
|
fprintf(stderr, " -t (preserve src_dev rx timestamp)\n");
|
||||||
fprintf(stderr, " -e (echo sent frames - recommended on vcanx)\n");
|
fprintf(stderr, " -e (echo sent frames - recommended on vcanx)\n");
|
||||||
fprintf(stderr, " -i (allow to route to incoming interface)\n");
|
fprintf(stderr, " -i (allow to route to incoming interface)\n");
|
||||||
@@ -243,34 +247,35 @@ void print_usage(char *prg)
|
|||||||
fprintf(stderr, " -p <profile>:[<profile_data>] (CRC8 checksum profile & parameters)\n");
|
fprintf(stderr, " -p <profile>:[<profile_data>] (CRC8 checksum profile & parameters)\n");
|
||||||
fprintf(stderr, "\nValues are given and expected in hexadecimal values. Leading 0s can be omitted.\n");
|
fprintf(stderr, "\nValues are given and expected in hexadecimal values. Leading 0s can be omitted.\n");
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "<filter> is a <value><mask> CAN identifier filter\n");
|
fprintf(stderr, "<filter> is a <value><mask> CAN identifier filter:\n");
|
||||||
fprintf(stderr, " <can_id>:<can_mask> (matches when <received_can_id> & mask == can_id & mask)\n");
|
fprintf(stderr, " <can_id>:<can_mask> (matches when <received_can_id> & mask == can_id & mask)\n");
|
||||||
fprintf(stderr, " <can_id>~<can_mask> (matches when <received_can_id> & mask != can_id & mask)\n");
|
fprintf(stderr, " <can_id>~<can_mask> (matches when <received_can_id> & mask != can_id & mask)\n");
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "<mod> is a CAN frame modification instruction consisting of\n");
|
fprintf(stderr, "<mod> is a CAN frame modification instruction consisting of\n");
|
||||||
fprintf(stderr, "<instruction>:<can_frame-elements>:<can_id>.<can_dlc>.<can_data>\n");
|
fprintf(stderr, "<instruction>:<can_frame-elements>:<can_id>.<can_dlc>.<can_data>\n");
|
||||||
fprintf(stderr, " - <instruction> is one of 'AND' 'OR' 'XOR' 'SET'\n");
|
fprintf(stderr, " <instruction> is one of 'AND' 'OR' 'XOR' 'SET'\n");
|
||||||
fprintf(stderr, " - <can_frame-elements> is _one_ or _more_ of 'I'dentifier 'L'ength 'D'ata\n");
|
fprintf(stderr, " <can_frame-elements> is _one_ or _more_ of 'I'dentifier 'L'ength 'D'ata\n");
|
||||||
fprintf(stderr, " - <can_id> is an u32 value containing the CAN Identifier\n");
|
fprintf(stderr, " <can_id> is an u32 value containing the CAN Identifier\n");
|
||||||
fprintf(stderr, " - <can_dlc> is an u8 value containing the data length code (0 .. 8)\n");
|
fprintf(stderr, " <can_dlc> is an u8 value containing the data length code (0 .. 8)\n");
|
||||||
fprintf(stderr, " - <can_data> is always eight(!) u8 values containing the CAN frames data\n");
|
fprintf(stderr, " <can_data> is always eight(!) u8 values containing the CAN frames data\n");
|
||||||
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "<MOD> is a CAN FD frame modification instruction consisting of\n");
|
fprintf(stderr, "<MOD> is a CAN FD frame modification instruction consisting of\n");
|
||||||
fprintf(stderr, "<instruction>:<canfd_frame-elements>:<can_id>.<flags>.<len>.<can_data>\n");
|
fprintf(stderr, "<instruction>:<canfd_frame-elements>:<can_id>.<flags>.<len>.<can_data>\n");
|
||||||
fprintf(stderr, " - <instruction> is one of 'AND' 'OR' 'XOR' 'SET'\n");
|
fprintf(stderr, " <instruction> is one of 'AND' 'OR' 'XOR' 'SET'\n");
|
||||||
fprintf(stderr, " - <canfd_frame-elements> is _one_ or _more_ of 'I'd 'F'lags 'L'ength 'D'ata\n");
|
fprintf(stderr, " <canfd_frame-elements> is _one_ or _more_ of 'I'd 'F'lags 'L'ength 'D'ata\n");
|
||||||
fprintf(stderr, " - <can_id> is an u32 value containing the CAN FD Identifier\n");
|
fprintf(stderr, " <can_id> is an u32 value containing the CAN FD Identifier\n");
|
||||||
fprintf(stderr, " - <flags> is an u8 value containing CAN FD flags (CANFD_BRS, CANFD_ESI)\n");
|
fprintf(stderr, " <flags> is an u8 value containing CAN FD flags (CANFD_BRS, CANFD_ESI)\n");
|
||||||
fprintf(stderr, " - <len> is an u8 value containing the data length (0 .. 64)\n");
|
fprintf(stderr, " <len> is an u8 value containing the data length (0 .. 64)\n");
|
||||||
fprintf(stderr, " - <can_data> is always 64(!) u8 values containing the CAN FD frames data\n");
|
fprintf(stderr, " <can_data> is always 64(!) u8 values containing the CAN FD frames data\n");
|
||||||
fprintf(stderr, "The max. four modifications are performed in the order AND -> OR -> XOR -> SET\n");
|
fprintf(stderr, "The max. four modifications are performed in the order AND -> OR -> XOR -> SET\n");
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "Example:\n");
|
|
||||||
fprintf(stderr, "%s -A -s can0 -d vcan3 -e -f 123:C00007FF -m SET:IL:333.4.1122334455667788\n", prg);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
fprintf(stderr, "Supported CRC 8 profiles:\n");
|
fprintf(stderr, "Supported CRC 8 profiles:\n");
|
||||||
fprintf(stderr, "Profile '%d' (1U8) - add one additional u8 value\n", CGW_CRC8PRF_1U8);
|
fprintf(stderr, " Profile '%d' (1U8) add one additional u8 value\n", CGW_CRC8PRF_1U8);
|
||||||
fprintf(stderr, "Profile '%d' (16U8) - add u8 value from table[16] indexed by (data[1] & 0xF)\n", CGW_CRC8PRF_16U8);
|
fprintf(stderr, " Profile '%d' (16U8) add u8 value from table[16] indexed by (data[1] & 0xF)\n", CGW_CRC8PRF_16U8);
|
||||||
fprintf(stderr, "Profile '%d' (SFFID_XOR) - add u8 value (can_id & 0xFF) ^ (can_id >> 8 & 0xFF)\n", CGW_CRC8PRF_SFFID_XOR);
|
fprintf(stderr, " Profile '%d' (SFFID_XOR) add u8 value (can_id & 0xFF) ^ (can_id >> 8 & 0xFF)\n", CGW_CRC8PRF_SFFID_XOR);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
fprintf(stderr, "Examples:\n");
|
||||||
|
fprintf(stderr, "%s -A -s can0 -d vcan3 -e -f 123:C00007FF -m SET:IL:333.4.1122334455667788\n", prg);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,14 +295,14 @@ int parse_crc8_profile(char *optarg, struct cgw_csum_crc8 *crc8)
|
|||||||
int ret = 1;
|
int ret = 1;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
|
||||||
if (sscanf(optarg, "%hhd:", &crc8->profile) != 1)
|
if (sscanf(optarg, "%hhu:", &crc8->profile) != 1)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
switch (crc8->profile) {
|
switch (crc8->profile) {
|
||||||
|
|
||||||
case CGW_CRC8PRF_1U8:
|
case CGW_CRC8PRF_1U8:
|
||||||
|
|
||||||
if (sscanf(optarg, "%hhd:%2hhx", &crc8->profile, &crc8->profile_data[0]) == 2)
|
if (sscanf(optarg, "%hhu:%2hhx", &crc8->profile, &crc8->profile_data[0]) == 2)
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -701,8 +706,8 @@ int main(int argc, char **argv)
|
|||||||
struct can_filter filter;
|
struct can_filter filter;
|
||||||
struct sockaddr_nl nladdr;
|
struct sockaddr_nl nladdr;
|
||||||
|
|
||||||
struct cgw_csum_xor cs_xor;
|
struct cgw_csum_xor cs_xor = { 0 };
|
||||||
struct cgw_csum_crc8 cs_crc8;
|
struct cgw_csum_crc8 cs_crc8 = { 0 };
|
||||||
char crc8tab[513] = {0};
|
char crc8tab[513] = {0};
|
||||||
|
|
||||||
struct modattr modmsg[CGW_MOD_FUNCS];
|
struct modattr modmsg[CGW_MOD_FUNCS];
|
||||||
@@ -712,8 +717,6 @@ int main(int argc, char **argv)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
memset(&req, 0, sizeof(req));
|
memset(&req, 0, sizeof(req));
|
||||||
memset(&cs_xor, 0, sizeof(cs_xor));
|
|
||||||
memset(&cs_crc8, 0, sizeof(cs_crc8));
|
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "ADFLs:d:Xteiu:l:f:c:p:x:m:M:?")) != -1) {
|
while ((opt = getopt(argc, argv, "ADFLs:d:Xteiu:l:f:c:p:x:m:M:?")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
@@ -767,7 +770,7 @@ int main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
if (sscanf(optarg, "%hhd", &limit_hops) != 1 || !(limit_hops)) {
|
if (sscanf(optarg, "%hhu", &limit_hops) != 1 || !(limit_hops)) {
|
||||||
printf("Bad hop limit definition '%s'.\n", optarg);
|
printf("Bad hop limit definition '%s'.\n", optarg);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-21
@@ -42,29 +42,29 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/uio.h>
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <linux/can.h>
|
#include <linux/can.h>
|
||||||
#include <linux/can/raw.h>
|
#include <linux/can/raw.h>
|
||||||
#include <linux/sockios.h>
|
#include <linux/sockios.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
|
|
||||||
@@ -89,7 +89,8 @@ void print_usage(char *prg)
|
|||||||
{
|
{
|
||||||
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
|
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
|
||||||
fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg);
|
fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg);
|
||||||
fprintf(stderr, "Options: -m <mask> (ID filter mask. Default 0x00000000) *\n");
|
fprintf(stderr, "Options:\n");
|
||||||
|
fprintf(stderr, " -m <mask> (ID filter mask. Default 0x00000000) *\n");
|
||||||
fprintf(stderr, " -v <value> (ID filter value. Default 0x00000000) *\n");
|
fprintf(stderr, " -v <value> (ID filter value. Default 0x00000000) *\n");
|
||||||
fprintf(stderr, " -i <0|1> (invert the specified ID filter) *\n");
|
fprintf(stderr, " -i <0|1> (invert the specified ID filter) *\n");
|
||||||
fprintf(stderr, " -e <emask> (mask for error frames)\n");
|
fprintf(stderr, " -e <emask> (mask for error frames)\n");
|
||||||
@@ -139,7 +140,7 @@ int idx2dindex(int ifidx, int socket)
|
|||||||
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
|
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
|
||||||
perror("SIOCGIFNAME");
|
perror("SIOCGIFNAME");
|
||||||
|
|
||||||
if (max_devname_len < strlen(ifr.ifr_name))
|
if (max_devname_len < (int)strlen(ifr.ifr_name))
|
||||||
max_devname_len = strlen(ifr.ifr_name);
|
max_devname_len = strlen(ifr.ifr_name);
|
||||||
|
|
||||||
strcpy(devname[i], ifr.ifr_name);
|
strcpy(devname[i], ifr.ifr_name);
|
||||||
@@ -280,8 +281,12 @@ int main(int argc, char **argv)
|
|||||||
inaddr.sin_port = htons(port);
|
inaddr.sin_port = htons(port);
|
||||||
|
|
||||||
while(bind(socki, (struct sockaddr*)&inaddr, sizeof(inaddr)) < 0) {
|
while(bind(socki, (struct sockaddr*)&inaddr, sizeof(inaddr)) < 0) {
|
||||||
|
struct timespec f = {
|
||||||
|
.tv_nsec = 100 * 1000 * 1000,
|
||||||
|
};
|
||||||
|
|
||||||
printf(".");fflush(NULL);
|
printf(".");fflush(NULL);
|
||||||
usleep(100000);
|
nanosleep(&f, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listen(socki, 3) != 0) {
|
if (listen(socki, 3) != 0) {
|
||||||
@@ -295,7 +300,6 @@ int main(int argc, char **argv)
|
|||||||
//printf("accepted\n");
|
//printf("accepted\n");
|
||||||
if (!fork())
|
if (!fork())
|
||||||
break;
|
break;
|
||||||
else
|
|
||||||
close(accsocket);
|
close(accsocket);
|
||||||
}
|
}
|
||||||
else if (errno != EINTR) {
|
else if (errno != EINTR) {
|
||||||
@@ -352,15 +356,14 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
addr.can_family = AF_CAN;
|
addr.can_family = AF_CAN;
|
||||||
|
|
||||||
if (strcmp(ANYDEV, argv[optind+i])) {
|
if (strcmp(ANYDEV, argv[optind + i]) != 0) {
|
||||||
strcpy(ifr.ifr_name, argv[optind+i]);
|
strcpy(ifr.ifr_name, argv[optind+i]);
|
||||||
if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
|
if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
|
||||||
perror("SIOCGIFINDEX");
|
perror("SIOCGIFINDEX");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
addr.can_ifindex = ifr.ifr_ifindex;
|
addr.can_ifindex = ifr.ifr_ifindex;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
addr.can_ifindex = 0; /* any can interface */
|
addr.can_ifindex = 0; /* any can interface */
|
||||||
|
|
||||||
if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||||
@@ -409,7 +412,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
idx = idx2dindex(addr.can_ifindex, s[i]);
|
idx = idx2dindex(addr.can_ifindex, s[i]);
|
||||||
|
|
||||||
sprintf(temp, "(%ld.%06ld) %*s ",
|
sprintf(temp, "(%lu.%06lu) %*s ",
|
||||||
tv.tv_sec, tv.tv_usec, max_devname_len, devname[idx]);
|
tv.tv_sec, tv.tv_usec, max_devname_len, devname[idx]);
|
||||||
sprint_canframe(temp+strlen(temp), &frame, 0, maxdlen);
|
sprint_canframe(temp+strlen(temp), &frame, 0, maxdlen);
|
||||||
strcat(temp, "\n");
|
strcat(temp, "\n");
|
||||||
@@ -421,7 +424,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* print CAN frame in log file style to stdout */
|
/* print CAN frame in log file style to stdout */
|
||||||
printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
|
printf("(%lu.%06lu) ", tv.tv_sec, tv.tv_usec);
|
||||||
printf("%*s ", max_devname_len, devname[idx]);
|
printf("%*s ", max_devname_len, devname[idx]);
|
||||||
fprint_canframe(stdout, &frame, "\n", 0, maxdlen);
|
fprint_canframe(stdout, &frame, "\n", 0, maxdlen);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+22
-20
@@ -42,19 +42,19 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <libgen.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <libgen.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <linux/can.h>
|
#include <linux/can.h>
|
||||||
#include <linux/can/raw.h>
|
#include <linux/can/raw.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
|
|
||||||
@@ -77,8 +77,10 @@ extern int optind, opterr, optopt;
|
|||||||
|
|
||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
|
fprintf(stderr, "%s - replay a compact CAN frame logfile to CAN devices.\n", prg);
|
||||||
fprintf(stderr, "\nUsage: %s <options> [interface assignment]*\n\n", prg);
|
fprintf(stderr, "\nUsage: %s <options> [interface assignment]*\n\n", prg);
|
||||||
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
|
fprintf(stderr, "Options:\n");
|
||||||
|
fprintf(stderr, " -I <infile> (default stdin)\n");
|
||||||
fprintf(stderr, " -l <num> "
|
fprintf(stderr, " -l <num> "
|
||||||
"(process input file <num> times)\n"
|
"(process input file <num> times)\n"
|
||||||
" "
|
" "
|
||||||
@@ -93,14 +95,14 @@ 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\n");
|
"sent CAN frames)\n\n");
|
||||||
fprintf(stderr, "Interface assignment: 0..n assignments like "
|
fprintf(stderr, "Interface assignment:\n");
|
||||||
"<write-if>=<log-if>\n");
|
fprintf(stderr, " 0..n assignments like <write-if>=<log-if>\n\n");
|
||||||
fprintf(stderr, "e.g. vcan2=can0 ( send frames received from can0 on "
|
fprintf(stderr, " e.g. vcan2=can0 (send frames received from can0 on "
|
||||||
"vcan2 )\n");
|
"vcan2)\n");
|
||||||
fprintf(stderr, "extra hook: stdout=can0 ( print logfile line marked with can0 on "
|
fprintf(stderr, " extra hook: stdout=can0 (print logfile line marked with can0 on "
|
||||||
"stdout )\n");
|
"stdout)\n");
|
||||||
fprintf(stderr, "No assignments => send frames to the interface(s) they "
|
fprintf(stderr, " No assignments => send frames to the interface(s) they "
|
||||||
"had been received from.\n\n");
|
"had been received from\n\n");
|
||||||
fprintf(stderr, "Lines in the logfile not beginning with '(' (start of "
|
fprintf(stderr, "Lines in the logfile not beginning with '(' (start of "
|
||||||
"timestamp) are ignored.\n\n");
|
"timestamp) are ignored.\n\n");
|
||||||
}
|
}
|
||||||
@@ -213,7 +215,7 @@ int add_assignment(char *mode, int socket, char *txname, char *rxname,
|
|||||||
}
|
}
|
||||||
strcpy(asgn[i].rxif, rxname);
|
strcpy(asgn[i].rxif, rxname);
|
||||||
|
|
||||||
if (strcmp(txname, "stdout")) {
|
if (strcmp(txname, "stdout") != 0) {
|
||||||
strcpy(ifr.ifr_name, txname);
|
strcpy(ifr.ifr_name, txname);
|
||||||
if (ioctl(socket, SIOCGIFINDEX, &ifr) < 0) {
|
if (ioctl(socket, SIOCGIFINDEX, &ifr) < 0) {
|
||||||
perror("SIOCGIFINDEX");
|
perror("SIOCGIFINDEX");
|
||||||
@@ -357,7 +359,7 @@ int main(int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
strcpy(buf, argv[optind+i]);
|
strcpy(buf, argv[optind+i]);
|
||||||
for (j=0; j<BUFSZ; j++) { /* find '=' in assignment */
|
for (j=0; j<(int)BUFSZ; j++) { /* find '=' in assignment */
|
||||||
if (buf[j] == '=')
|
if (buf[j] == '=')
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -393,7 +395,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
eof = 0;
|
eof = 0;
|
||||||
|
|
||||||
if (sscanf(buf, "(%ld.%ld) %s %s", &log_tv.tv_sec, &log_tv.tv_usec,
|
if (sscanf(buf, "(%lu.%lu) %s %s", &log_tv.tv_sec, &log_tv.tv_usec,
|
||||||
device, ascframe) != 4) {
|
device, ascframe) != 4) {
|
||||||
fprintf(stderr, "incorrect line format in logfile\n");
|
fprintf(stderr, "incorrect line format in logfile\n");
|
||||||
return 1;
|
return 1;
|
||||||
@@ -472,7 +474,7 @@ int main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sscanf(buf, "(%ld.%ld) %s %s", &log_tv.tv_sec, &log_tv.tv_usec,
|
if (sscanf(buf, "(%lu.%lu) %s %s", &log_tv.tv_sec, &log_tv.tv_usec,
|
||||||
device, ascframe) != 4) {
|
device, ascframe) != 4) {
|
||||||
fprintf(stderr, "incorrect line format in logfile\n");
|
fprintf(stderr, "incorrect line format in logfile\n");
|
||||||
return 1;
|
return 1;
|
||||||
@@ -493,7 +495,7 @@ int main(int argc, char **argv)
|
|||||||
/* test for logfile timestamps jumping backwards OR */
|
/* test for logfile timestamps jumping backwards OR */
|
||||||
/* if the user likes to skip long gaps in the timestamps */
|
/* if the user likes to skip long gaps in the timestamps */
|
||||||
if ((last_log_tv.tv_sec > log_tv.tv_sec) ||
|
if ((last_log_tv.tv_sec > log_tv.tv_sec) ||
|
||||||
(skipgap && labs(last_log_tv.tv_sec - log_tv.tv_sec) > skipgap))
|
(skipgap && labs(last_log_tv.tv_sec - log_tv.tv_sec) > (long)skipgap))
|
||||||
create_diff_tv(&today_tv, &diff_tv, &log_tv);
|
create_diff_tv(&today_tv, &diff_tv, &log_tv);
|
||||||
|
|
||||||
last_log_tv = log_tv;
|
last_log_tv = log_tv;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
|
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
|
||||||
/*
|
/*
|
||||||
* cansend.c - simple command line tool to send CAN-frames via CAN_RAW sockets
|
* cansend.c - send CAN-frames via CAN_RAW sockets
|
||||||
*
|
*
|
||||||
* Copyright (c) 2002-2007 Volkswagen Group Electronic Research
|
* Copyright (c) 2002-2007 Volkswagen Group Electronic Research
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
@@ -56,6 +56,29 @@
|
|||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
|
|
||||||
|
void print_usage(char *prg)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s - send CAN-frames via CAN_RAW sockets.\n", prg);
|
||||||
|
fprintf(stderr, "\nUsage: %s <device> <can_frame>.\n", prg);
|
||||||
|
fprintf(stderr, "\n<can_frame>:\n");
|
||||||
|
fprintf(stderr, " <can_id>#{data} for 'classic' CAN 2.0 data frames\n");
|
||||||
|
fprintf(stderr, " <can_id>#R{len} for 'classic' CAN 2.0 data frames\n");
|
||||||
|
fprintf(stderr, " <can_id>##<flags>{data} for CAN FD frames\n\n");
|
||||||
|
fprintf(stderr, "<can_id>:\n"
|
||||||
|
" 3 (SFF) or 8 (EFF) hex chars\n");
|
||||||
|
fprintf(stderr, "{data}:\n"
|
||||||
|
" 0..8 (0..64 CAN FD) ASCII hex-values (optionally separated by '.')\n");
|
||||||
|
fprintf(stderr, "{len}:\n"
|
||||||
|
" an optional 0..8 value as RTR frames can contain a valid dlc field\n");
|
||||||
|
fprintf(stderr, "<flags>:\n"
|
||||||
|
" a single ASCII Hex value (0 .. F) which defines canfd_frame.flags\n\n");
|
||||||
|
fprintf(stderr, "Examples:\n");
|
||||||
|
fprintf(stderr, " 5A1#11.2233.44556677.88 / 123#DEADBEEF / 5AA# / 123##1 / 213##311223344 /\n"
|
||||||
|
" 1F334455#1122334455667788 / 123#R / 00000123#R3\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int s; /* can raw socket */
|
int s; /* can raw socket */
|
||||||
@@ -68,27 +91,15 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
/* check command line options */
|
/* check command line options */
|
||||||
if (argc != 3) {
|
if (argc != 3) {
|
||||||
fprintf(stderr, "Usage: %s <device> <can_frame>.\n", argv[0]);
|
print_usage(argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse CAN frame */
|
/* parse CAN frame */
|
||||||
required_mtu = parse_canframe(argv[2], &frame);
|
required_mtu = parse_canframe(argv[2], &frame);
|
||||||
if (!required_mtu){
|
if (!required_mtu){
|
||||||
fprintf(stderr, "\nWrong CAN-frame format! Try:\n\n");
|
fprintf(stderr, "\nWrong CAN-frame format!\n\n");
|
||||||
fprintf(stderr, " <can_id>#{data} for 'classic' CAN 2.0 data frames\n");
|
print_usage(argv[0]);
|
||||||
fprintf(stderr, " <can_id>#R{len} for 'classic' CAN 2.0 RTR frames\n");
|
|
||||||
fprintf(stderr, " <can_id>##<flags>{data} for CAN FD frames\n\n");
|
|
||||||
fprintf(stderr, "<can_id> can have 3 (SFF) or 8 (EFF) hex chars\n");
|
|
||||||
fprintf(stderr, "{data} has 0..8 (0..64 CAN FD) ASCII hex-values (optionally");
|
|
||||||
fprintf(stderr, " separated by '.')\n");
|
|
||||||
fprintf(stderr, "{len} is an optional 0..8 value as RTR frames can contain a");
|
|
||||||
fprintf(stderr, " valid dlc field\n");
|
|
||||||
fprintf(stderr, "<flags> a single ASCII Hex value (0 .. F) which defines");
|
|
||||||
fprintf(stderr, " canfd_frame.flags\n\n");
|
|
||||||
fprintf(stderr, "e.g. 5A1#11.2233.44556677.88 / 123#DEADBEEF / 5AA# / ");
|
|
||||||
fprintf(stderr, "123##1 / 213##311223344\n 1F334455#1122334455667788 / ");
|
|
||||||
fprintf(stderr, "123#R / 00000123#R3\n\n");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +121,7 @@ int main(int argc, char **argv)
|
|||||||
addr.can_family = AF_CAN;
|
addr.can_family = AF_CAN;
|
||||||
addr.can_ifindex = ifr.ifr_ifindex;
|
addr.can_ifindex = ifr.ifr_ifindex;
|
||||||
|
|
||||||
if (required_mtu > CAN_MTU) {
|
if (required_mtu > (int)CAN_MTU) {
|
||||||
|
|
||||||
/* check if the frame fits into the CAN netdevice */
|
/* check if the frame fits into the CAN netdevice */
|
||||||
if (ioctl(s, SIOCGIFMTU, &ifr) < 0) {
|
if (ioctl(s, SIOCGIFMTU, &ifr) < 0) {
|
||||||
|
|||||||
+367
@@ -0,0 +1,367 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
// Copyright (c) 2007, 2008, 2009, 2010, 2014, 2015, 2019 Pengutronix,
|
||||||
|
// Marc Kleine-Budde <kernel@pengutronix.de>
|
||||||
|
// Copyright (c) 2005 Pengutronix,
|
||||||
|
// Sascha Hauer <kernel@pengutronix.de>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
|
||||||
|
#include <linux/can.h>
|
||||||
|
#include <linux/can/raw.h>
|
||||||
|
|
||||||
|
#define CAN_ID_DEFAULT (2)
|
||||||
|
|
||||||
|
extern int optind, opterr, optopt;
|
||||||
|
|
||||||
|
static int s = -1;
|
||||||
|
static bool running = true;
|
||||||
|
static bool infinite = true;
|
||||||
|
static unsigned int drop_until_quit;
|
||||||
|
static unsigned int drop_count;
|
||||||
|
static bool use_poll = false;
|
||||||
|
|
||||||
|
static unsigned int loopcount = 1;
|
||||||
|
static int verbose;
|
||||||
|
|
||||||
|
static struct can_frame frame = {
|
||||||
|
.can_dlc = 1,
|
||||||
|
};
|
||||||
|
static struct can_filter filter[] = {
|
||||||
|
{ .can_id = CAN_ID_DEFAULT, },
|
||||||
|
};
|
||||||
|
|
||||||
|
static void print_usage(char *prg)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: %s [<can-interface>] [Options]\n"
|
||||||
|
"\n"
|
||||||
|
"cansequence sends CAN messages with a rising sequence number as payload.\n"
|
||||||
|
"When the -r option is given, cansequence expects to receive these messages\n"
|
||||||
|
"and prints an error message if a wrong sequence number is encountered.\n"
|
||||||
|
"The main purpose of this program is to test the reliability of CAN links.\n"
|
||||||
|
"\n"
|
||||||
|
"Options:\n"
|
||||||
|
" -e, --extended send extended frame\n"
|
||||||
|
" -i, --identifier=ID CAN Identifier (default = %u)\n"
|
||||||
|
" --loop=COUNT send message COUNT times\n"
|
||||||
|
" -p, --poll use poll(2) to wait for buffer space while sending\n"
|
||||||
|
" -q, --quit <num> quit if <num> wrong sequences are encountered\n"
|
||||||
|
" -r, --receive work as receiver\n"
|
||||||
|
" -v, --verbose be verbose (twice to be even more verbose\n"
|
||||||
|
" -h, --help this help\n"
|
||||||
|
" --version print version information and exit\n",
|
||||||
|
prg, CAN_ID_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sig_handler(int signo)
|
||||||
|
{
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void do_receive()
|
||||||
|
{
|
||||||
|
uint8_t ctrlmsg[CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(sizeof(__u32))];
|
||||||
|
struct iovec iov = {
|
||||||
|
.iov_base = &frame,
|
||||||
|
};
|
||||||
|
struct msghdr msg = {
|
||||||
|
.msg_iov = &iov,
|
||||||
|
.msg_iovlen = 1,
|
||||||
|
.msg_control = &ctrlmsg,
|
||||||
|
};
|
||||||
|
const int dropmonitor_on = 1;
|
||||||
|
bool sequence_init = true;
|
||||||
|
unsigned int sequence_wrap = 0;
|
||||||
|
uint32_t sequence_mask = 0xff;
|
||||||
|
uint32_t sequence_rx = 0;
|
||||||
|
uint32_t sequence_delta = 0;
|
||||||
|
uint32_t sequence = 0;
|
||||||
|
unsigned int overflow_old = 0;
|
||||||
|
can_err_mask_t err_mask = CAN_ERR_MASK;
|
||||||
|
|
||||||
|
if (setsockopt(s, SOL_SOCKET, SO_RXQ_OVFL,
|
||||||
|
&dropmonitor_on, sizeof(dropmonitor_on)) < 0) {
|
||||||
|
perror("setsockopt() SO_RXQ_OVFL not supported by your Linux Kernel");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* enable recv. of error messages */
|
||||||
|
if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &err_mask, sizeof(err_mask))) {
|
||||||
|
perror("setsockopt()");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* enable recv. now */
|
||||||
|
if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, filter, sizeof(filter))) {
|
||||||
|
perror("setsockopt()");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((infinite || loopcount--) && running) {
|
||||||
|
ssize_t nbytes;
|
||||||
|
|
||||||
|
msg.msg_iov[0].iov_len = sizeof(frame);
|
||||||
|
msg.msg_controllen = sizeof(ctrlmsg);
|
||||||
|
msg.msg_flags = 0;
|
||||||
|
|
||||||
|
nbytes = recvmsg(s, &msg, 0);
|
||||||
|
if (nbytes < 0) {
|
||||||
|
perror("read()");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frame.can_id & CAN_ERR_FLAG) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"sequence CNT: %6u, ERRORFRAME %7x %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||||
|
sequence, frame.can_id,
|
||||||
|
frame.data[0], frame.data[1], frame.data[2], frame.data[3],
|
||||||
|
frame.data[4], frame.data[5], frame.data[6], frame.data[7]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sequence_rx = frame.data[0];
|
||||||
|
|
||||||
|
if (sequence_init) {
|
||||||
|
sequence_init = false;
|
||||||
|
sequence = sequence_rx;
|
||||||
|
}
|
||||||
|
|
||||||
|
sequence_delta = (sequence_rx - sequence) & sequence_mask;
|
||||||
|
if (sequence_delta) {
|
||||||
|
struct cmsghdr *cmsg;
|
||||||
|
uint32_t overflow = 0;
|
||||||
|
uint32_t overflow_delta;
|
||||||
|
|
||||||
|
drop_count++;
|
||||||
|
|
||||||
|
for (cmsg = CMSG_FIRSTHDR(&msg);
|
||||||
|
cmsg && (cmsg->cmsg_level == SOL_SOCKET);
|
||||||
|
cmsg = CMSG_NXTHDR(&msg,cmsg)) {
|
||||||
|
if (cmsg->cmsg_type == SO_RXQ_OVFL) {
|
||||||
|
memcpy(&overflow, CMSG_DATA(cmsg), sizeof(overflow));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
overflow_delta = overflow - overflow_old;
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
"sequence CNT: %6u, RX: %6u expected: %3u missing: %4u skt overfl d: %4u a: %4u delta: %3u incident: %u\n",
|
||||||
|
sequence, sequence_rx,
|
||||||
|
sequence & sequence_mask, sequence_delta,
|
||||||
|
overflow_delta, overflow,
|
||||||
|
sequence_delta - overflow_delta,
|
||||||
|
drop_count);
|
||||||
|
|
||||||
|
if (drop_count == drop_until_quit)
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
|
sequence = sequence_rx;
|
||||||
|
overflow_old = overflow;
|
||||||
|
} else if (verbose > 1) {
|
||||||
|
printf("sequence CNT: %6u, RX: %6u\n", sequence, sequence_rx);
|
||||||
|
}
|
||||||
|
|
||||||
|
sequence++;
|
||||||
|
if (verbose && !(sequence & sequence_mask))
|
||||||
|
printf("sequence wrap around (%d)\n", sequence_wrap++);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_send()
|
||||||
|
{
|
||||||
|
unsigned int seq_wrap = 0;
|
||||||
|
uint8_t sequence = 0;
|
||||||
|
|
||||||
|
while ((infinite || loopcount--) && running) {
|
||||||
|
ssize_t len;
|
||||||
|
|
||||||
|
if (verbose > 1)
|
||||||
|
printf("sending frame. sequence number: %d\n", sequence);
|
||||||
|
|
||||||
|
again:
|
||||||
|
len = write(s, &frame, sizeof(frame));
|
||||||
|
if (len == -1) {
|
||||||
|
switch (errno) {
|
||||||
|
case ENOBUFS: {
|
||||||
|
int err;
|
||||||
|
struct pollfd fds[] = {
|
||||||
|
{
|
||||||
|
.fd = s,
|
||||||
|
.events = POLLOUT,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!use_poll) {
|
||||||
|
perror("write");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = poll(fds, 1, 1000);
|
||||||
|
if (err == -1 && errno != -EINTR) {
|
||||||
|
perror("poll()");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case EINTR: /* fallthrough */
|
||||||
|
goto again;
|
||||||
|
default:
|
||||||
|
perror("write");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
frame.data[0]++;
|
||||||
|
sequence++;
|
||||||
|
|
||||||
|
if (verbose && !sequence)
|
||||||
|
printf("sequence wrap around (%d)\n", seq_wrap++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sigaction act = {
|
||||||
|
.sa_handler = sig_handler,
|
||||||
|
};
|
||||||
|
struct ifreq ifr;
|
||||||
|
struct sockaddr_can addr;
|
||||||
|
char *interface = "can0";
|
||||||
|
int family = PF_CAN, type = SOCK_RAW, proto = CAN_RAW;
|
||||||
|
int extended = 0;
|
||||||
|
int receive = 0;
|
||||||
|
int opt;
|
||||||
|
|
||||||
|
sigaction(SIGINT, &act, NULL);
|
||||||
|
sigaction(SIGTERM, &act, NULL);
|
||||||
|
sigaction(SIGHUP, &act, NULL);
|
||||||
|
|
||||||
|
struct option long_options[] = {
|
||||||
|
{ "extended", no_argument, 0, 'e' },
|
||||||
|
{ "identifier", required_argument, 0, 'i' },
|
||||||
|
{ "loop", required_argument, 0, 'l' },
|
||||||
|
{ "poll", no_argument, 0, 'p' },
|
||||||
|
{ "quit", optional_argument, 0, 'q' },
|
||||||
|
{ "receive", no_argument, 0, 'r' },
|
||||||
|
{ "verbose", no_argument, 0, 'v' },
|
||||||
|
{ "help", no_argument, 0, 'h' },
|
||||||
|
{ 0, 0, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
while ((opt = getopt_long(argc, argv, "ei:pq::rvh", long_options, NULL)) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'e':
|
||||||
|
extended = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'i':
|
||||||
|
filter->can_id = strtoul(optarg, NULL, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'r':
|
||||||
|
receive = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'l':
|
||||||
|
if (optarg) {
|
||||||
|
loopcount = strtoul(optarg, NULL, 0);
|
||||||
|
infinite = false;
|
||||||
|
} else {
|
||||||
|
infinite = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
use_poll = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'q':
|
||||||
|
if (optarg)
|
||||||
|
drop_until_quit = strtoul(optarg, NULL, 0);
|
||||||
|
else
|
||||||
|
drop_until_quit = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'v':
|
||||||
|
verbose++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
print_usage(basename(argv[0]));
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
print_usage(basename(argv[0]));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argv[optind] != NULL)
|
||||||
|
interface = argv[optind];
|
||||||
|
|
||||||
|
if (extended) {
|
||||||
|
filter->can_mask = CAN_EFF_MASK;
|
||||||
|
filter->can_id &= CAN_EFF_MASK;
|
||||||
|
filter->can_id |= CAN_EFF_FLAG;
|
||||||
|
} else {
|
||||||
|
filter->can_mask = CAN_SFF_MASK;
|
||||||
|
filter->can_id &= CAN_SFF_MASK;
|
||||||
|
}
|
||||||
|
frame.can_id = filter->can_id;
|
||||||
|
filter->can_mask |= CAN_EFF_FLAG;
|
||||||
|
|
||||||
|
printf("interface = %s, family = %d, type = %d, proto = %d\n",
|
||||||
|
interface, family, type, proto);
|
||||||
|
|
||||||
|
s = socket(family, type, proto);
|
||||||
|
if (s < 0) {
|
||||||
|
perror("socket()");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
addr.can_family = family;
|
||||||
|
strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name));
|
||||||
|
if (ioctl(s, SIOCGIFINDEX, &ifr)) {
|
||||||
|
perror("ioctl()");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
addr.can_ifindex = ifr.ifr_ifindex;
|
||||||
|
|
||||||
|
/* first don't recv. any msgs */
|
||||||
|
if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0)) {
|
||||||
|
perror("setsockopt()");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||||
|
perror("bind()");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (receive)
|
||||||
|
do_receive();
|
||||||
|
else
|
||||||
|
do_send();
|
||||||
|
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
+368
-277
@@ -1,6 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
|
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
|
||||||
/*
|
/*
|
||||||
* cansniffer.c
|
* cansniffer.c - volatile CAN content visualizer
|
||||||
*
|
*
|
||||||
* Copyright (c) 2002-2007 Volkswagen Group Electronic Research
|
* Copyright (c) 2002-2007 Volkswagen Group Electronic Research
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
@@ -42,32 +42,35 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <fcntl.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <libgen.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#include <net/if.h>
|
|
||||||
|
|
||||||
#include <linux/can.h>
|
#include <linux/can.h>
|
||||||
#include <linux/can/bcm.h>
|
#include <linux/can/raw.h>
|
||||||
#include <linux/sockios.h>
|
#include <linux/sockios.h>
|
||||||
|
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
|
|
||||||
#define SETFNAME "sniffset."
|
#define SETFNAME "sniffset."
|
||||||
#define ANYDEV "any"
|
#define ANYDEV "any"
|
||||||
|
#define MAX_SLOTS 2048
|
||||||
|
|
||||||
/* flags */
|
/* flags */
|
||||||
|
|
||||||
@@ -92,9 +95,10 @@
|
|||||||
|
|
||||||
#define ATTCOLOR ATTBOLD FGRED
|
#define ATTCOLOR ATTBOLD FGRED
|
||||||
|
|
||||||
#define STARTLINESTR "XX delta ID data ... "
|
#define LDL " | " /* long delimiter */
|
||||||
|
#define SDL "|" /* short delimiter for binary on 80 chars terminal */
|
||||||
|
|
||||||
struct snif {
|
static struct snif {
|
||||||
int flags;
|
int flags;
|
||||||
long hold;
|
long hold;
|
||||||
long timeout;
|
long timeout;
|
||||||
@@ -104,75 +108,118 @@ struct snif {
|
|||||||
struct can_frame current;
|
struct can_frame current;
|
||||||
struct can_frame marker;
|
struct can_frame marker;
|
||||||
struct can_frame notch;
|
struct can_frame notch;
|
||||||
} sniftab[2048];
|
} sniftab[MAX_SLOTS];
|
||||||
|
|
||||||
|
|
||||||
extern int optind, opterr, optopt;
|
extern int optind, opterr, optopt;
|
||||||
|
|
||||||
|
static int idx;
|
||||||
static int running = 1;
|
static int running = 1;
|
||||||
static int clearscreen = 1;
|
static int clearscreen = 1;
|
||||||
|
static int print_eff;
|
||||||
static int notch;
|
static int notch;
|
||||||
static int filter_id_only;
|
|
||||||
static long timeout = TIMEOUT;
|
static long timeout = TIMEOUT;
|
||||||
static long hold = HOLD;
|
static long hold = HOLD;
|
||||||
static long loop = LOOP;
|
static long loop = LOOP;
|
||||||
static unsigned char binary;
|
static unsigned char binary;
|
||||||
|
static unsigned char binary8;
|
||||||
static unsigned char binary_gap;
|
static unsigned char binary_gap;
|
||||||
static unsigned char color;
|
static unsigned char color;
|
||||||
static char *interface;
|
static char *interface;
|
||||||
|
static char *vdl = LDL; /* variable delimiter */
|
||||||
|
static char *ldl = LDL; /* long delimiter */
|
||||||
|
|
||||||
void rx_setup (int fd, int id);
|
void print_snifline(int slot);
|
||||||
void rx_delete (int fd, int id);
|
int handle_keyb(void);
|
||||||
void print_snifline(int id);
|
int handle_frame(int fd, long currcms);
|
||||||
int handle_keyb(int fd);
|
int handle_timeo(long currcms);
|
||||||
int handle_bcm(int fd, long currcms);
|
|
||||||
int handle_timeo(int fd, long currcms);
|
|
||||||
void writesettings(char* name);
|
void writesettings(char* name);
|
||||||
void readsettings(char* name, int sockfd);
|
int readsettings(char* name);
|
||||||
|
int sniftab_index(canid_t id);
|
||||||
|
|
||||||
|
void switchvdl(char *delim)
|
||||||
|
{
|
||||||
|
/* reduce delimiter size for EFF IDs in binary display of up
|
||||||
|
to 8 data bytes payload to fit into 80 chars per line */
|
||||||
|
if (binary8)
|
||||||
|
vdl = delim;
|
||||||
|
}
|
||||||
|
|
||||||
|
int comp(const void *elem1, const void *elem2)
|
||||||
|
{
|
||||||
|
unsigned long f = ((struct snif*)elem1)->current.can_id;
|
||||||
|
unsigned long s = ((struct snif*)elem2)->current.can_id;
|
||||||
|
|
||||||
|
if (f > s)
|
||||||
|
return 1;
|
||||||
|
if (f < s)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
const char manual [] = {
|
const char manual [] = {
|
||||||
"commands that can be entered at runtime:\n"
|
"commands that can be entered at runtime:\n"
|
||||||
"\n"
|
" q<ENTER> - quit\n"
|
||||||
"q<ENTER> - quit\n"
|
" b<ENTER> - toggle binary / HEX-ASCII output\n"
|
||||||
"b<ENTER> - toggle binary / HEX-ASCII output\n"
|
" 8<ENTER> - toggle binary / HEX-ASCII output (small for EFF on 80 chars)\n"
|
||||||
"B<ENTER> - toggle binary with gap / HEX-ASCII output (exceeds 80 chars!)\n"
|
" B<ENTER> - toggle binary with gap / HEX-ASCII output (exceeds 80 chars!)\n"
|
||||||
"c<ENTER> - toggle color mode\n"
|
" c<ENTER> - toggle color mode\n"
|
||||||
"#<ENTER> - notch currently marked/changed bits (can be used repeatedly)\n"
|
" <SPACE><ENTER> - force a clear screen\n"
|
||||||
"*<ENTER> - clear notched marked\n"
|
" #<ENTER> - notch currently marked/changed bits (can be used repeatedly)\n"
|
||||||
"rMYNAME<ENTER> - read settings file (filter/notch)\n"
|
" *<ENTER> - clear notched marked\n"
|
||||||
"wMYNAME<ENTER> - write settings file (filter/notch)\n"
|
" rMYNAME<ENTER> - read settings file (filter/notch)\n"
|
||||||
"+FILTER<ENTER> - add CAN-IDs to sniff\n"
|
" wMYNAME<ENTER> - write settings file (filter/notch)\n"
|
||||||
"-FILTER<ENTER> - remove CAN-IDs to sniff\n"
|
" a<ENTER> - enable 'a'll SFF CAN-IDs to sniff\n"
|
||||||
|
" n<ENTER> - enable 'n'one SFF CAN-IDs to sniff\n"
|
||||||
|
" A<ENTER> - enable 'A'll EFF CAN-IDs to sniff\n"
|
||||||
|
" N<ENTER> - enable 'N'one EFF CAN-IDs to sniff\n"
|
||||||
|
" +FILTER<ENTER> - add CAN-IDs to sniff\n"
|
||||||
|
" -FILTER<ENTER> - remove CAN-IDs to sniff\n"
|
||||||
"\n"
|
"\n"
|
||||||
"FILTER can be a single CAN-ID or a CAN-ID/Bitmask:\n"
|
"FILTER can be a single CAN-ID or a CAN-ID/Bitmask:\n"
|
||||||
"+1F5<ENTER> - add CAN-ID 0x1F5\n"
|
"\n"
|
||||||
"-42E<ENTER> - remove CAN-ID 0x42E\n"
|
" single SFF 11 bit IDs:\n"
|
||||||
"-42E7FF<ENTER> - remove CAN-ID 0x42E (using Bitmask)\n"
|
" +1F5<ENTER> - add SFF CAN-ID 0x1F5\n"
|
||||||
"-500700<ENTER> - remove CAN-IDs 0x500 - 0x5FF\n"
|
" -42E<ENTER> - remove SFF CAN-ID 0x42E\n"
|
||||||
"+400600<ENTER> - add CAN-IDs 0x400 - 0x5FF\n"
|
"\n"
|
||||||
"+000000<ENTER> - add all CAN-IDs\n"
|
" single EFF 29 bit IDs:\n"
|
||||||
"-000000<ENTER> - remove all CAN-IDs\n"
|
" +18FEDF55<ENTER> - add EFF CAN-ID 0x18FEDF55\n"
|
||||||
|
" -00000090<ENTER> - remove EFF CAN-ID 0x00000090\n"
|
||||||
|
"\n"
|
||||||
|
" CAN-ID/Bitmask SFF:\n"
|
||||||
|
" -42E7FF<ENTER> - remove SFF CAN-ID 0x42E (using Bitmask)\n"
|
||||||
|
" -500700<ENTER> - remove SFF CAN-IDs 0x500 - 0x5FF\n"
|
||||||
|
" +400600<ENTER> - add SFF CAN-IDs 0x400 - 0x5FF\n"
|
||||||
|
" +000000<ENTER> - add all SFF CAN-IDs\n"
|
||||||
|
" -000000<ENTER> - remove all SFF CAN-IDs\n"
|
||||||
|
"\n"
|
||||||
|
" CAN-ID/Bitmask EFF:\n"
|
||||||
|
" -0000000000000000<ENTER> - remove all EFF CAN-IDs\n"
|
||||||
|
" +12345678000000FF<ENTER> - add EFF CAN IDs xxxxxx78\n"
|
||||||
|
" +0000000000000000<ENTER> - add all EFF CAN-IDs\n"
|
||||||
"\n"
|
"\n"
|
||||||
"if (id & filter) == (sniff-id & filter) the action (+/-) is performed,\n"
|
"if (id & filter) == (sniff-id & filter) the action (+/-) is performed,\n"
|
||||||
"which is quite easy when the filter is 000\n"
|
"which is quite easy when the filter is 000 resp. 00000000 for EFF.\n"
|
||||||
"\n"
|
"\n"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fprintf(stderr, "%s - volatile CAN content visualizer.\n", prg);
|
||||||
fprintf(stderr, "\nUsage: %s [can-interface]\n", prg);
|
fprintf(stderr, "\nUsage: %s [can-interface]\n", prg);
|
||||||
fprintf(stderr, "Options: -m <mask> (initial FILTER default 0x00000000)\n");
|
fprintf(stderr, "Options:\n");
|
||||||
fprintf(stderr, " -v <value> (initial FILTER default 0x00000000)\n");
|
|
||||||
fprintf(stderr, " -q (quiet - all IDs deactivated)\n");
|
fprintf(stderr, " -q (quiet - all IDs deactivated)\n");
|
||||||
fprintf(stderr, " -r <name> (read %sname from file)\n", SETFNAME);
|
fprintf(stderr, " -r <name> (read %sname from file)\n", SETFNAME);
|
||||||
|
fprintf(stderr, " -e (fix extended frame format output - no auto detect)\n");
|
||||||
fprintf(stderr, " -b (start with binary mode)\n");
|
fprintf(stderr, " -b (start with binary mode)\n");
|
||||||
|
fprintf(stderr, " -8 (start with binary mode - for EFF on 80 chars)\n");
|
||||||
fprintf(stderr, " -B (start with binary mode with gap - exceeds 80 chars!)\n");
|
fprintf(stderr, " -B (start with binary mode with gap - exceeds 80 chars!)\n");
|
||||||
fprintf(stderr, " -c (color changes)\n");
|
fprintf(stderr, " -c (color changes)\n");
|
||||||
fprintf(stderr, " -f (filter on CAN-ID only)\n");
|
|
||||||
fprintf(stderr, " -t <time> (timeout for ID display [x10ms] default: %d, 0 = OFF)\n", TIMEOUT);
|
fprintf(stderr, " -t <time> (timeout for ID display [x10ms] default: %d, 0 = OFF)\n", TIMEOUT);
|
||||||
fprintf(stderr, " -h <time> (hold marker on changes [x10ms] default: %d)\n", HOLD);
|
fprintf(stderr, " -h <time> (hold marker on changes [x10ms] default: %d)\n", HOLD);
|
||||||
fprintf(stderr, " -l <time> (loop time (display) [x10ms] default: %d)\n", LOOP);
|
fprintf(stderr, " -l <time> (loop time (display) [x10ms] default: %d)\n", LOOP);
|
||||||
fprintf(stderr, "Use interface name '%s' to receive from all can-interfaces\n", ANYDEV);
|
fprintf(stderr, " -? (print this help text)\n");
|
||||||
|
fprintf(stderr, "Use interface name '%s' to receive from all can-interfaces.\n", ANYDEV);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "%s", manual);
|
fprintf(stderr, "%s", manual);
|
||||||
}
|
}
|
||||||
@@ -186,37 +233,28 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
fd_set rdfs;
|
fd_set rdfs;
|
||||||
int s;
|
int s;
|
||||||
canid_t mask = 0;
|
|
||||||
canid_t value = 0;
|
|
||||||
long currcms = 0;
|
long currcms = 0;
|
||||||
long lastcms = 0;
|
long lastcms = 0;
|
||||||
unsigned char quiet = 0;
|
unsigned char quiet = 0;
|
||||||
int opt, ret;
|
int opt, ret;
|
||||||
struct timeval timeo, start_tv, tv;
|
struct timeval timeo, start_tv, tv;
|
||||||
struct sockaddr_can addr;
|
struct sockaddr_can addr;
|
||||||
struct ifreq ifr;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
||||||
signal(SIGTERM, sigterm);
|
signal(SIGTERM, sigterm);
|
||||||
signal(SIGHUP, sigterm);
|
signal(SIGHUP, sigterm);
|
||||||
signal(SIGINT, sigterm);
|
signal(SIGINT, sigterm);
|
||||||
|
|
||||||
for (i=0; i < 2048 ;i++) /* default: check all CAN-IDs */
|
for (i = 0; i < MAX_SLOTS ;i++) /* default: enable all slots */
|
||||||
do_set(i, ENABLE);
|
do_set(i, ENABLE);
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "m:v:r:t:h:l:qbBcf?")) != -1) {
|
while ((opt = getopt(argc, argv, "r:t:h:l:qeb8Bc?")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'm':
|
|
||||||
sscanf(optarg, "%x", &mask);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'v':
|
|
||||||
sscanf(optarg, "%x", &value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
readsettings(optarg, 0); /* no BCM-setting here */
|
if (readsettings(optarg) < 0) {
|
||||||
|
fprintf(stderr, "Unable to read setting file '%s%s'!\n", SETFNAME, optarg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
@@ -235,11 +273,22 @@ int main(int argc, char **argv)
|
|||||||
quiet = 1;
|
quiet = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'e':
|
||||||
|
print_eff = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'b':
|
case 'b':
|
||||||
binary = 1;
|
binary = 1;
|
||||||
binary_gap = 0;
|
binary_gap = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case '8':
|
||||||
|
binary = 1;
|
||||||
|
binary8 = 1; /* enable variable delimiter for EFF */
|
||||||
|
switchvdl(SDL); /* switch directly to short delimiter */
|
||||||
|
binary_gap = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'B':
|
case 'B':
|
||||||
binary = 1;
|
binary = 1;
|
||||||
binary_gap = 1;
|
binary_gap = 1;
|
||||||
@@ -249,11 +298,9 @@ int main(int argc, char **argv)
|
|||||||
color = 1;
|
color = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'f':
|
|
||||||
filter_id_only = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '?':
|
case '?':
|
||||||
|
print_usage(basename(argv[0]));
|
||||||
|
exit(0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -268,16 +315,8 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (quiet)
|
if (quiet)
|
||||||
for (i = 0; i < 2048; i++)
|
for (i = 0; i < MAX_SLOTS; i++)
|
||||||
do_clr(i, ENABLE);
|
do_clr(i, ENABLE);
|
||||||
else if (mask || value) {
|
|
||||||
for (i=0; i < 2048 ;i++) {
|
|
||||||
if ((i & mask) == (value & mask))
|
|
||||||
do_set(i, ENABLE);
|
|
||||||
else
|
|
||||||
do_clr(i, ENABLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strlen(argv[optind]) >= IFNAMSIZ) {
|
if (strlen(argv[optind]) >= IFNAMSIZ) {
|
||||||
printf("name of CAN device '%s' is too long!\n", argv[optind]);
|
printf("name of CAN device '%s' is too long!\n", argv[optind]);
|
||||||
@@ -286,33 +325,24 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
interface = argv[optind];
|
interface = argv[optind];
|
||||||
|
|
||||||
if ((s = socket(PF_CAN, SOCK_DGRAM, CAN_BCM)) < 0) {
|
s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
||||||
|
if (s < 0) {
|
||||||
perror("socket");
|
perror("socket");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
addr.can_family = AF_CAN;
|
addr.can_family = AF_CAN;
|
||||||
|
|
||||||
if (strcmp(ANYDEV, argv[optind])) {
|
if (strcmp(ANYDEV, argv[optind]) != 0)
|
||||||
strcpy(ifr.ifr_name, argv[optind]);
|
addr.can_ifindex = if_nametoindex(argv[optind]);
|
||||||
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
|
|
||||||
perror("SIOCGIFINDEX");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
addr.can_ifindex = ifr.ifr_ifindex;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
addr.can_ifindex = 0; /* any can interface */
|
addr.can_ifindex = 0; /* any can interface */
|
||||||
|
|
||||||
if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||||
perror("connect");
|
perror("connect");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i < 2048 ;i++) /* initial BCM setup */
|
|
||||||
if (is_set(i, ENABLE))
|
|
||||||
rx_setup(s, i);
|
|
||||||
|
|
||||||
gettimeofday(&start_tv, NULL);
|
gettimeofday(&start_tv, NULL);
|
||||||
tv.tv_sec = tv.tv_usec = 0;
|
tv.tv_sec = tv.tv_usec = 0;
|
||||||
|
|
||||||
@@ -337,13 +367,13 @@ int main(int argc, char **argv)
|
|||||||
currcms = (tv.tv_sec - start_tv.tv_sec) * 100 + (tv.tv_usec / 10000);
|
currcms = (tv.tv_sec - start_tv.tv_sec) * 100 + (tv.tv_usec / 10000);
|
||||||
|
|
||||||
if (FD_ISSET(0, &rdfs))
|
if (FD_ISSET(0, &rdfs))
|
||||||
running &= handle_keyb(s);
|
running &= handle_keyb();
|
||||||
|
|
||||||
if (FD_ISSET(s, &rdfs))
|
if (FD_ISSET(s, &rdfs))
|
||||||
running &= handle_bcm(s, currcms);
|
running &= handle_frame(s, currcms);
|
||||||
|
|
||||||
if (currcms - lastcms >= loop) {
|
if (currcms - lastcms >= loop) {
|
||||||
running &= handle_timeo(s, currcms);
|
running &= handle_timeo(currcms);
|
||||||
lastcms = currcms;
|
lastcms = currcms;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -354,85 +384,99 @@ int main(int argc, char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rx_setup (int fd, int id){
|
void do_modify_sniftab(unsigned int value, unsigned int mask, char cmd)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
struct {
|
for (i = 0; i < idx ;i++) {
|
||||||
struct bcm_msg_head msg_head;
|
if ((sniftab[i].current.can_id & mask) == (value & mask)) {
|
||||||
struct can_frame frame;
|
if (cmd == '+')
|
||||||
} txmsg;
|
do_set(i, ENABLE);
|
||||||
|
else
|
||||||
txmsg.msg_head.opcode = RX_SETUP;
|
do_clr(i, ENABLE);
|
||||||
txmsg.msg_head.can_id = id;
|
}
|
||||||
txmsg.msg_head.flags = RX_CHECK_DLC;
|
}
|
||||||
txmsg.msg_head.ival1.tv_sec = 0;
|
|
||||||
txmsg.msg_head.ival1.tv_usec = 0;
|
|
||||||
txmsg.msg_head.ival2.tv_sec = 0;
|
|
||||||
txmsg.msg_head.ival2.tv_usec = 0;
|
|
||||||
txmsg.msg_head.nframes = 1;
|
|
||||||
|
|
||||||
/* set all bits to be relevant */
|
|
||||||
memset(&txmsg.frame.data, 0xFF, 8);
|
|
||||||
|
|
||||||
if (filter_id_only)
|
|
||||||
txmsg.msg_head.flags |= RX_FILTER_ID;
|
|
||||||
|
|
||||||
if (write(fd, &txmsg, sizeof(txmsg)) < 0)
|
|
||||||
perror("write");
|
|
||||||
};
|
|
||||||
|
|
||||||
void rx_delete (int fd, int id){
|
|
||||||
|
|
||||||
struct bcm_msg_head msg_head;
|
|
||||||
|
|
||||||
msg_head.opcode = RX_DELETE;
|
|
||||||
msg_head.can_id = id;
|
|
||||||
msg_head.nframes = 0;
|
|
||||||
|
|
||||||
if (write(fd, &msg_head, sizeof(msg_head)) < 0)
|
|
||||||
perror("write");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int handle_keyb(int fd){
|
int handle_keyb(void)
|
||||||
|
{
|
||||||
char cmd [20] = {0};
|
char cmd [25] = {0};
|
||||||
int i;
|
int i, clen;
|
||||||
unsigned int mask;
|
unsigned int mask;
|
||||||
unsigned int value;
|
unsigned int value;
|
||||||
|
|
||||||
if (read(0, cmd, 19) > strlen("+123456\n"))
|
if (read(0, cmd, 24) > (long)strlen("+1234567812345678\n"))
|
||||||
return 1; /* ignore */
|
return 1; /* ignore */
|
||||||
|
|
||||||
if (strlen(cmd) > 0)
|
if (strlen(cmd) > 0)
|
||||||
cmd[strlen(cmd)-1] = 0; /* chop off trailing newline */
|
cmd[strlen(cmd)-1] = 0; /* chop off trailing newline */
|
||||||
|
|
||||||
|
clen = strlen(&cmd[1]); /* content length behind command */
|
||||||
|
|
||||||
switch (cmd[0]) {
|
switch (cmd[0]) {
|
||||||
|
|
||||||
case '+':
|
case '+':
|
||||||
case '-':
|
case '-':
|
||||||
|
if (clen == 6) {
|
||||||
|
/* masking strict SFF ID content vvvmmm */
|
||||||
sscanf(&cmd[1], "%x", &value);
|
sscanf(&cmd[1], "%x", &value);
|
||||||
if (strlen(&cmd[1]) > 3) {
|
mask = value | 0xFFFF800; /* cleared flags! */
|
||||||
mask = value & 0xFFF;
|
|
||||||
value >>= 12;
|
value >>= 12;
|
||||||
|
value &= 0x7FF;
|
||||||
|
do_modify_sniftab(value, mask, cmd[0]);
|
||||||
|
break;
|
||||||
|
} else if (clen == 16) {
|
||||||
|
sscanf(&cmd[9], "%x", &mask);
|
||||||
|
cmd[9] = 0; /* terminate 'value' */
|
||||||
|
sscanf(&cmd[1], "%x", &value);
|
||||||
|
mask |= CAN_EFF_FLAG;
|
||||||
|
value |= CAN_EFF_FLAG;
|
||||||
|
do_modify_sniftab(value, mask, cmd[0]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
mask = 0x7FF;
|
|
||||||
|
|
||||||
if (cmd[0] == '+') {
|
/* check for single SFF/EFF CAN ID length */
|
||||||
for (i=0; i < 2048 ;i++) {
|
if (!((clen == 3) || (clen == 8)))
|
||||||
if (((i & mask) == (value & mask)) && (is_clr(i, ENABLE))) {
|
break;
|
||||||
|
|
||||||
|
/* enable/disable single SFF/EFF CAN ID */
|
||||||
|
sscanf(&cmd[1], "%x", &value);
|
||||||
|
if (clen == 8)
|
||||||
|
value |= CAN_EFF_FLAG;
|
||||||
|
|
||||||
|
i = sniftab_index(value);
|
||||||
|
if (i < 0)
|
||||||
|
break; /* No Match */
|
||||||
|
|
||||||
|
if (cmd[0] == '+')
|
||||||
do_set(i, ENABLE);
|
do_set(i, ENABLE);
|
||||||
rx_setup(fd, i);
|
else
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { /* '-' */
|
|
||||||
for (i=0; i < 2048 ;i++) {
|
|
||||||
if (((i & mask) == (value & mask)) && (is_set(i, ENABLE))) {
|
|
||||||
do_clr(i, ENABLE);
|
do_clr(i, ENABLE);
|
||||||
rx_delete(fd, i);
|
|
||||||
}
|
break;
|
||||||
}
|
|
||||||
}
|
case 'a' : /* all SFF CAN IDs */
|
||||||
|
value = 0;
|
||||||
|
mask = 0xFFFF800; /* cleared flags! */
|
||||||
|
do_modify_sniftab(value, mask, '+');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'n' : /* none SFF CAN IDs */
|
||||||
|
value = 0;
|
||||||
|
mask = 0xFFFF800; /* cleared flags! */
|
||||||
|
do_modify_sniftab(value, mask, '-');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'A' : /* all EFF CAN IDs */
|
||||||
|
value = CAN_EFF_FLAG;
|
||||||
|
mask = CAN_EFF_FLAG;
|
||||||
|
do_modify_sniftab(value, mask, '+');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'N' : /* none EFF CAN IDs */
|
||||||
|
value = CAN_EFF_FLAG;
|
||||||
|
mask = CAN_EFF_FLAG;
|
||||||
|
do_modify_sniftab(value, mask, '-');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'w' :
|
case 'w' :
|
||||||
@@ -440,7 +484,7 @@ int handle_keyb(int fd){
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'r' :
|
case 'r' :
|
||||||
readsettings(&cmd[1], fd);
|
readsettings(&cmd[1]); /* don't care about success */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'q' :
|
case 'q' :
|
||||||
@@ -449,6 +493,7 @@ int handle_keyb(int fd){
|
|||||||
|
|
||||||
case 'B' :
|
case 'B' :
|
||||||
binary_gap = 1;
|
binary_gap = 1;
|
||||||
|
switchvdl(LDL);
|
||||||
if (binary)
|
if (binary)
|
||||||
binary = 0;
|
binary = 0;
|
||||||
else
|
else
|
||||||
@@ -456,13 +501,19 @@ int handle_keyb(int fd){
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case '8' :
|
||||||
|
binary8 = 1;
|
||||||
|
/* fallthrough */
|
||||||
|
|
||||||
case 'b' :
|
case 'b' :
|
||||||
binary_gap = 0;
|
binary_gap = 0;
|
||||||
if (binary)
|
if (binary) {
|
||||||
binary = 0;
|
binary = 0;
|
||||||
else
|
switchvdl(LDL);
|
||||||
|
} else {
|
||||||
binary = 1;
|
binary = 1;
|
||||||
|
switchvdl(SDL);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c' :
|
case 'c' :
|
||||||
@@ -473,12 +524,16 @@ int handle_keyb(int fd){
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ' ' :
|
||||||
|
clearscreen = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case '#' :
|
case '#' :
|
||||||
notch = 1;
|
notch = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '*' :
|
case '*' :
|
||||||
for (i=0; i < 2048; i++)
|
for (i = 0; i < idx; i++)
|
||||||
memset(&sniftab[i].notch.data, 0, 8);
|
memset(&sniftab[i].notch.data, 0, 8);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -489,68 +544,104 @@ int handle_keyb(int fd){
|
|||||||
clearscreen = 1;
|
clearscreen = 1;
|
||||||
|
|
||||||
return 1; /* ok */
|
return 1; /* ok */
|
||||||
};
|
}
|
||||||
|
|
||||||
int handle_bcm(int fd, long currcms){
|
int handle_frame(int fd, long currcms)
|
||||||
|
{
|
||||||
|
bool rx_changed = false;
|
||||||
|
bool run_qsort = false;
|
||||||
|
int nbytes, i, pos;
|
||||||
|
struct can_frame cf;
|
||||||
|
|
||||||
int nbytes, id, i;
|
if ((nbytes = read(fd, &cf, sizeof(cf))) < 0) {
|
||||||
|
perror("raw read");
|
||||||
struct {
|
|
||||||
struct bcm_msg_head msg_head;
|
|
||||||
struct can_frame frame;
|
|
||||||
} bmsg;
|
|
||||||
|
|
||||||
if ((nbytes = read(fd, &bmsg, sizeof(bmsg))) < 0) {
|
|
||||||
perror("bcm read");
|
|
||||||
return 0; /* quit */
|
return 0; /* quit */
|
||||||
}
|
}
|
||||||
|
|
||||||
id = bmsg.msg_head.can_id;
|
if (nbytes != CAN_MTU) {
|
||||||
ioctl(fd, SIOCGSTAMP, &sniftab[id].currstamp);
|
printf("received strange frame data length %d!\n", nbytes);
|
||||||
|
|
||||||
if (bmsg.msg_head.opcode != RX_CHANGED) {
|
|
||||||
printf("received strange BCM opcode %d!\n", bmsg.msg_head.opcode);
|
|
||||||
return 0; /* quit */
|
return 0; /* quit */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbytes != sizeof(bmsg)) {
|
if (!print_eff && (cf.can_id & CAN_EFF_FLAG)) {
|
||||||
printf("received strange BCM data length %d!\n", nbytes);
|
print_eff = 1;
|
||||||
return 0; /* quit */
|
clearscreen = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sniftab[id].current = bmsg.frame;
|
pos = sniftab_index(cf.can_id);
|
||||||
for (i=0; i < 8; i++)
|
if (pos < 0) {
|
||||||
sniftab[id].marker.data[i] |= sniftab[id].current.data[i] ^ sniftab[id].last.data[i];
|
/* CAN ID not existing */
|
||||||
|
if (idx < MAX_SLOTS) {
|
||||||
|
/* assign new slot */
|
||||||
|
pos = idx++;
|
||||||
|
rx_changed = true;
|
||||||
|
run_qsort = true;
|
||||||
|
} else {
|
||||||
|
/* informative exit */
|
||||||
|
perror("number of different CAN IDs exceeded MAX_SLOTS");
|
||||||
|
return 0; /* quit */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (cf.can_dlc == sniftab[pos].current.can_dlc)
|
||||||
|
for (i = 0; i < cf.can_dlc; i++) {
|
||||||
|
if (cf.data[i] != sniftab[pos].current.data[i] ) {
|
||||||
|
rx_changed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rx_changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
sniftab[id].timeout = (timeout)?(currcms + timeout):0;
|
/* print received frame even if the data didn't change to get a gap time */
|
||||||
|
if ((sniftab[pos].laststamp.tv_sec == 0) && (sniftab[pos].laststamp.tv_usec == 0))
|
||||||
|
rx_changed = true;
|
||||||
|
|
||||||
if (is_clr(id, DISPLAY))
|
if (rx_changed == true) {
|
||||||
|
sniftab[pos].laststamp = sniftab[pos].currstamp;
|
||||||
|
ioctl(fd, SIOCGSTAMP, &sniftab[pos].currstamp);
|
||||||
|
|
||||||
|
sniftab[pos].current = cf;
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
sniftab[pos].marker.data[i] |= sniftab[pos].current.data[i] ^ sniftab[pos].last.data[i];
|
||||||
|
|
||||||
|
sniftab[pos].timeout = (timeout)?(currcms + timeout):0;
|
||||||
|
|
||||||
|
if (is_clr(pos, DISPLAY))
|
||||||
clearscreen = 1; /* new entry -> new drawing */
|
clearscreen = 1; /* new entry -> new drawing */
|
||||||
|
|
||||||
do_set(id, DISPLAY);
|
do_set(pos, DISPLAY);
|
||||||
do_set(id, UPDATE);
|
do_set(pos, UPDATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (run_qsort == true)
|
||||||
|
qsort(sniftab, idx, sizeof(sniftab[0]), comp);
|
||||||
|
|
||||||
return 1; /* ok */
|
return 1; /* ok */
|
||||||
};
|
}
|
||||||
|
|
||||||
int handle_timeo(int fd, long currcms){
|
|
||||||
|
|
||||||
|
int handle_timeo(long currcms)
|
||||||
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
int force_redraw = 0;
|
int force_redraw = 0;
|
||||||
static unsigned int frame_count;
|
static unsigned int frame_count;
|
||||||
|
|
||||||
if (clearscreen) {
|
if (clearscreen) {
|
||||||
char startline[80];
|
if (print_eff)
|
||||||
printf("%s%s", CLR_SCREEN, CSR_HOME);
|
printf("%s%sXX|ms%s-- ID --%sdata ... < %s # l=%ld h=%ld t=%ld slots=%d >",
|
||||||
snprintf(startline, 79, "< cansniffer %s # l=%ld h=%ld t=%ld >", interface, loop, hold, timeout);
|
CLR_SCREEN, CSR_HOME, vdl, vdl, interface, loop, hold, timeout, idx);
|
||||||
printf("%s%*s",STARTLINESTR, 79-(int)strlen(STARTLINESTR), startline);
|
else
|
||||||
|
printf("%s%sXX|ms%sID %sdata ... < %s # l=%ld h=%ld t=%ld slots=%d >",
|
||||||
|
CLR_SCREEN, CSR_HOME, ldl, ldl, interface, loop, hold, timeout, idx);
|
||||||
|
|
||||||
force_redraw = 1;
|
force_redraw = 1;
|
||||||
clearscreen = 0;
|
clearscreen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notch) {
|
if (notch) {
|
||||||
for (i=0; i < 2048; i++) {
|
for (i = 0; i < idx; i++) {
|
||||||
for (j=0; j < 8; j++)
|
for (j = 0; j < 8; j++)
|
||||||
sniftab[i].notch.data[j] |= sniftab[i].marker.data[j];
|
sniftab[i].notch.data[j] |= sniftab[i].marker.data[j];
|
||||||
}
|
}
|
||||||
notch = 0;
|
notch = 0;
|
||||||
@@ -560,19 +651,15 @@ int handle_timeo(int fd, long currcms){
|
|||||||
printf("%02d\n", frame_count++); /* rolling display update counter */
|
printf("%02d\n", frame_count++); /* rolling display update counter */
|
||||||
frame_count %= 100;
|
frame_count %= 100;
|
||||||
|
|
||||||
for (i=0; i < 2048; i++) {
|
for (i = 0; i < idx; i++) {
|
||||||
|
|
||||||
if is_set(i, ENABLE) {
|
if is_set(i, ENABLE) {
|
||||||
|
|
||||||
if is_set(i, DISPLAY) {
|
if is_set(i, DISPLAY) {
|
||||||
|
if (is_set(i, UPDATE) || (force_redraw)) {
|
||||||
if (is_set(i, UPDATE) || (force_redraw)){
|
|
||||||
print_snifline(i);
|
print_snifline(i);
|
||||||
sniftab[i].hold = currcms + hold;
|
sniftab[i].hold = currcms + hold;
|
||||||
do_clr(i, UPDATE);
|
do_clr(i, UPDATE);
|
||||||
}
|
}
|
||||||
else
|
else if ((sniftab[i].hold) && (sniftab[i].hold < currcms)) {
|
||||||
if ((sniftab[i].hold) && (sniftab[i].hold < currcms)) {
|
|
||||||
memset(&sniftab[i].marker.data, 0, 8);
|
memset(&sniftab[i].marker.data, 0, 8);
|
||||||
print_snifline(i);
|
print_snifline(i);
|
||||||
sniftab[i].hold = 0; /* disable update by hold */
|
sniftab[i].hold = 0; /* disable update by hold */
|
||||||
@@ -587,19 +674,18 @@ int handle_timeo(int fd, long currcms){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
sniftab[i].last = sniftab[i].current;
|
sniftab[i].last = sniftab[i].current;
|
||||||
sniftab[i].laststamp = sniftab[i].currstamp;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1; /* ok */
|
return 1; /* ok */
|
||||||
|
}
|
||||||
|
|
||||||
};
|
void print_snifline(int slot)
|
||||||
|
{
|
||||||
void print_snifline(int id){
|
long diffsec = sniftab[slot].currstamp.tv_sec - sniftab[slot].laststamp.tv_sec;
|
||||||
|
long diffusec = sniftab[slot].currstamp.tv_usec - sniftab[slot].laststamp.tv_usec;
|
||||||
long diffsec = sniftab[id].currstamp.tv_sec - sniftab[id].laststamp.tv_sec;
|
int dlc_diff = sniftab[slot].last.can_dlc - sniftab[slot].current.can_dlc;
|
||||||
long diffusec = sniftab[id].currstamp.tv_usec - sniftab[id].laststamp.tv_usec;
|
canid_t cid = sniftab[slot].current.can_id;
|
||||||
int dlc_diff = sniftab[id].last.can_dlc - sniftab[id].current.can_dlc;
|
|
||||||
int i,j;
|
int i,j;
|
||||||
|
|
||||||
if (diffusec < 0)
|
if (diffusec < 0)
|
||||||
@@ -608,23 +694,27 @@ void print_snifline(int id){
|
|||||||
if (diffsec < 0)
|
if (diffsec < 0)
|
||||||
diffsec = diffusec = 0;
|
diffsec = diffusec = 0;
|
||||||
|
|
||||||
if (diffsec > 10)
|
if (diffsec >= 100)
|
||||||
diffsec = 9, diffusec = 999999;
|
diffsec = 99, diffusec = 999999;
|
||||||
|
|
||||||
printf("%ld.%06ld %3X ", diffsec, diffusec, id);
|
if (cid & CAN_EFF_FLAG)
|
||||||
|
printf("%02ld%03ld%s%08X%s", diffsec, diffusec/1000, vdl, cid & CAN_EFF_MASK, vdl);
|
||||||
|
else if (print_eff)
|
||||||
|
printf("%02ld%03ld%s---- %03X%s", diffsec, diffusec/1000, vdl, cid & CAN_SFF_MASK, vdl);
|
||||||
|
else
|
||||||
|
printf("%02ld%03ld%s%03X%s", diffsec, diffusec/1000, ldl, cid & CAN_SFF_MASK, ldl);
|
||||||
|
|
||||||
if (binary) {
|
if (binary) {
|
||||||
|
for (i = 0; i < sniftab[slot].current.can_dlc; i++) {
|
||||||
for (i=0; i<sniftab[id].current.can_dlc; i++) {
|
for (j=7; j >= 0; j--) {
|
||||||
for (j=7; j>=0; j--) {
|
if ((color) && (sniftab[slot].marker.data[i] & 1<<j) &&
|
||||||
if ((color) && (sniftab[id].marker.data[i] & 1<<j) &&
|
(!(sniftab[slot].notch.data[i] & 1<<j)))
|
||||||
(!(sniftab[id].notch.data[i] & 1<<j)))
|
if (sniftab[slot].current.data[i] & 1<<j)
|
||||||
if (sniftab[id].current.data[i] & 1<<j)
|
|
||||||
printf("%s1%s", ATTCOLOR, ATTRESET);
|
printf("%s1%s", ATTCOLOR, ATTRESET);
|
||||||
else
|
else
|
||||||
printf("%s0%s", ATTCOLOR, ATTRESET);
|
printf("%s0%s", ATTCOLOR, ATTRESET);
|
||||||
else
|
else
|
||||||
if (sniftab[id].current.data[i] & 1<<j)
|
if (sniftab[slot].current.data[i] & 1<<j)
|
||||||
putchar('1');
|
putchar('1');
|
||||||
else
|
else
|
||||||
putchar('0');
|
putchar('0');
|
||||||
@@ -637,30 +727,29 @@ void print_snifline(int id){
|
|||||||
* when the can_dlc decreased (dlc_diff > 0),
|
* when the can_dlc decreased (dlc_diff > 0),
|
||||||
* we need to blank the former data printout
|
* we need to blank the former data printout
|
||||||
*/
|
*/
|
||||||
for (i=0; i<dlc_diff; i++) {
|
for (i = 0; i < dlc_diff; i++) {
|
||||||
printf(" ");
|
printf(" ");
|
||||||
if (binary_gap)
|
if (binary_gap)
|
||||||
putchar(' ');
|
putchar(' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
for (i = 0; i < sniftab[slot].current.can_dlc; i++)
|
||||||
for (i=0; i<sniftab[id].current.can_dlc; i++)
|
if ((color) && (sniftab[slot].marker.data[i] & ~sniftab[slot].notch.data[i]))
|
||||||
if ((color) && (sniftab[id].marker.data[i]) && (!(sniftab[id].notch.data[i])))
|
printf("%s%02X%s ", ATTCOLOR, sniftab[slot].current.data[i], ATTRESET);
|
||||||
printf("%s%02X%s ", ATTCOLOR, sniftab[id].current.data[i], ATTRESET);
|
|
||||||
else
|
else
|
||||||
printf("%02X ", sniftab[id].current.data[i]);
|
printf("%02X ", sniftab[slot].current.data[i]);
|
||||||
|
|
||||||
if (sniftab[id].current.can_dlc < 8)
|
if (sniftab[slot].current.can_dlc < 8)
|
||||||
printf("%*s", (8 - sniftab[id].current.can_dlc) * 3, "");
|
printf("%*s", (8 - sniftab[slot].current.can_dlc) * 3, "");
|
||||||
|
|
||||||
for (i=0; i<sniftab[id].current.can_dlc; i++)
|
for (i = 0; i<sniftab[slot].current.can_dlc; i++)
|
||||||
if ((sniftab[id].current.data[i] > 0x1F) &&
|
if ((sniftab[slot].current.data[i] > 0x1F) &&
|
||||||
(sniftab[id].current.data[i] < 0x7F))
|
(sniftab[slot].current.data[i] < 0x7F))
|
||||||
if ((color) && (sniftab[id].marker.data[i]) && (!(sniftab[id].notch.data[i])))
|
if ((color) && (sniftab[slot].marker.data[i] & ~sniftab[slot].notch.data[i]))
|
||||||
printf("%s%c%s", ATTCOLOR, sniftab[id].current.data[i], ATTRESET);
|
printf("%s%c%s", ATTCOLOR, sniftab[slot].current.data[i], ATTRESET);
|
||||||
else
|
else
|
||||||
putchar(sniftab[id].current.data[i]);
|
putchar(sniftab[slot].current.data[i]);
|
||||||
else
|
else
|
||||||
putchar('.');
|
putchar('.');
|
||||||
|
|
||||||
@@ -668,94 +757,96 @@ void print_snifline(int id){
|
|||||||
* when the can_dlc decreased (dlc_diff > 0),
|
* when the can_dlc decreased (dlc_diff > 0),
|
||||||
* we need to blank the former data printout
|
* we need to blank the former data printout
|
||||||
*/
|
*/
|
||||||
for (i=0; i<dlc_diff; i++)
|
for (i = 0; i < dlc_diff; i++)
|
||||||
putchar(' ');
|
putchar(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
|
|
||||||
memset(&sniftab[id].marker.data, 0, 8);
|
memset(&sniftab[slot].marker.data, 0, 8);
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
void writesettings(char* name){
|
|
||||||
|
|
||||||
|
void writesettings(char* name)
|
||||||
|
{
|
||||||
int fd;
|
int fd;
|
||||||
char fname[30] = SETFNAME;
|
char fname[30] = SETFNAME;
|
||||||
int i,j;
|
int i,j;
|
||||||
char buf[8]= {0};
|
char buf[13]= {0};
|
||||||
|
|
||||||
strncat(fname, name, 29 - strlen(fname));
|
strncat(fname, name, 29 - strlen(fname));
|
||||||
fd = open(fname, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
|
fd = open(fname, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
|
||||||
|
|
||||||
if (fd > 0) {
|
if (fd > 0) {
|
||||||
|
for (i = 0; i < idx ;i++) {
|
||||||
for (i=0; i < 2048 ;i++) {
|
sprintf(buf, "<%08X>%c.", sniftab[i].current.can_id, (is_set(i, ENABLE))?'1':'0');
|
||||||
sprintf(buf, "<%03X>%c.", i, (is_set(i, ENABLE))?'1':'0');
|
if (write(fd, buf, 12) < 0)
|
||||||
if (write(fd, buf, 7) < 0)
|
|
||||||
perror("write");
|
perror("write");
|
||||||
for (j=0; j<8 ; j++){
|
for (j = 0; j < 8 ; j++) {
|
||||||
sprintf(buf, "%02X", sniftab[i].notch.data[j]);
|
sprintf(buf, "%02X", sniftab[i].notch.data[j]);
|
||||||
if (write(fd, buf, 2) < 0)
|
if (write(fd, buf, 2) < 0)
|
||||||
perror("write");
|
perror("write");
|
||||||
}
|
}
|
||||||
if (write(fd, "\n", 1) < 0)
|
if (write(fd, "\n", 1) < 0)
|
||||||
perror("write");
|
perror("write");
|
||||||
/* 7 + 16 + 1 = 24 bytes per entry */
|
/* 12 + 16 + 1 = 29 bytes per entry */
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
printf("unable to write setting file '%s'!\n", fname);
|
printf("unable to write setting file '%s'!\n", fname);
|
||||||
};
|
}
|
||||||
|
|
||||||
void readsettings(char* name, int sockfd){
|
|
||||||
|
|
||||||
|
int readsettings(char* name)
|
||||||
|
{
|
||||||
int fd;
|
int fd;
|
||||||
char fname[30] = SETFNAME;
|
char fname[30] = SETFNAME;
|
||||||
char buf[25] = {0};
|
char buf[30] = {0};
|
||||||
int i,j;
|
int j;
|
||||||
|
bool done = false;
|
||||||
|
|
||||||
strncat(fname, name, 29 - strlen(fname));
|
strncat(fname, name, 29 - strlen(fname));
|
||||||
fd = open(fname, O_RDONLY);
|
fd = open(fname, O_RDONLY);
|
||||||
|
|
||||||
if (fd > 0) {
|
if (fd > 0) {
|
||||||
if (!sockfd)
|
idx = 0;
|
||||||
printf("reading setting file '%s' ... ", fname);
|
while (!done) {
|
||||||
|
if (read(fd, &buf, 29) == 29) {
|
||||||
|
unsigned long id = strtoul(&buf[1], (char **)NULL, 16);
|
||||||
|
|
||||||
for (i=0; i < 2048 ;i++) {
|
sniftab[idx].current.can_id = id;
|
||||||
if (read(fd, &buf, 24) == 24) {
|
|
||||||
if (buf[5] & 1) {
|
if (buf[10] & 1)
|
||||||
if (is_clr(i, ENABLE)) {
|
do_set(idx, ENABLE);
|
||||||
do_set(i, ENABLE);
|
else
|
||||||
if (sockfd)
|
do_clr(idx, ENABLE);
|
||||||
rx_setup(sockfd, i);
|
|
||||||
|
for (j = 7; j >= 0 ; j--) {
|
||||||
|
sniftab[idx].notch.data[j] =
|
||||||
|
(__u8) strtoul(&buf[2*j+12], (char **)NULL, 16) & 0xFF;
|
||||||
|
buf[2*j+12] = 0; /* cut off each time */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (++idx >= MAX_SLOTS)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (is_set(i, ENABLE)) {
|
done = true;
|
||||||
do_clr(i, ENABLE);
|
|
||||||
if (sockfd)
|
|
||||||
rx_delete(sockfd, i);
|
|
||||||
}
|
}
|
||||||
for (j=7; j>=0 ; j--){
|
|
||||||
sniftab[i].notch.data[j] =
|
|
||||||
(__u8) strtoul(&buf[2*j+7], (char **)NULL, 16) & 0xFF;
|
|
||||||
buf[2*j+7] = 0; /* cut off each time */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!sockfd)
|
|
||||||
printf("was only able to read until index %d from setting file '%s'!\n",
|
|
||||||
i, fname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sockfd)
|
|
||||||
printf("done\n");
|
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
printf("unable to read setting file '%s'!\n", fname);
|
return -1;
|
||||||
};
|
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sniftab_index(canid_t id)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i <= idx; i++)
|
||||||
|
if (id == sniftab[i].current.can_id)
|
||||||
|
return i;
|
||||||
|
|
||||||
|
return -1; /* No match */
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
|
/* SPDX-License-Identifier: ((GPL-2.0-only WITH Linux-syscall-note) OR BSD-3-Clause) */
|
||||||
/*
|
/*
|
||||||
* linux/can/isotp.h
|
* linux/can/isotp.h
|
||||||
*
|
*
|
||||||
* Definitions for isotp CAN sockets
|
* Definitions for isotp CAN sockets (ISO 15765-2:2016)
|
||||||
*
|
*
|
||||||
* Author: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
|
* Copyright (c) 2020 Volkswagen Group Electronic Research
|
||||||
* Copyright (c) 2008 Volkswagen Group Electronic Research
|
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -39,13 +39,12 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
* DAMAGE.
|
* DAMAGE.
|
||||||
*
|
|
||||||
* Send feedback to <linux-can@vger.kernel.org>
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CAN_ISOTP_H
|
#ifndef _UAPI_CAN_ISOTP_H
|
||||||
#define CAN_ISOTP_H
|
#define _UAPI_CAN_ISOTP_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
#include <linux/can.h>
|
#include <linux/can.h>
|
||||||
|
|
||||||
#define SOL_CAN_ISOTP (SOL_CAN_BASE + CAN_ISOTP)
|
#define SOL_CAN_ISOTP (SOL_CAN_BASE + CAN_ISOTP)
|
||||||
@@ -123,7 +122,6 @@ struct can_isotp_ll_options {
|
|||||||
/* by the CAN netdriver configuration */
|
/* by the CAN netdriver configuration */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* flags for isotp behaviour */
|
/* flags for isotp behaviour */
|
||||||
|
|
||||||
#define CAN_ISOTP_LISTEN_MODE 0x001 /* listen only (do not send FC) */
|
#define CAN_ISOTP_LISTEN_MODE 0x001 /* listen only (do not send FC) */
|
||||||
@@ -136,6 +134,7 @@ struct can_isotp_ll_options {
|
|||||||
#define CAN_ISOTP_FORCE_TXSTMIN 0x080 /* ignore stmin from received FC */
|
#define CAN_ISOTP_FORCE_TXSTMIN 0x080 /* ignore stmin from received FC */
|
||||||
#define CAN_ISOTP_FORCE_RXSTMIN 0x100 /* ignore CFs depending on rx stmin */
|
#define CAN_ISOTP_FORCE_RXSTMIN 0x100 /* ignore CFs depending on rx stmin */
|
||||||
#define CAN_ISOTP_RX_EXT_ADDR 0x200 /* different rx extended addressing */
|
#define CAN_ISOTP_RX_EXT_ADDR 0x200 /* different rx extended addressing */
|
||||||
|
#define CAN_ISOTP_WAIT_TX_DONE 0x400 /* wait for tx completion */
|
||||||
|
|
||||||
|
|
||||||
/* default values */
|
/* default values */
|
||||||
@@ -161,7 +160,6 @@ struct can_isotp_ll_options {
|
|||||||
* these default settings can be changed via sockopts.
|
* these default settings can be changed via sockopts.
|
||||||
* For that reason the STmin value is intentionally _not_ checked for
|
* For that reason the STmin value is intentionally _not_ checked for
|
||||||
* consistency and copied directly into the flow control (FC) frame.
|
* consistency and copied directly into the flow control (FC) frame.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#endif
|
#endif /* !_UAPI_CAN_ISOTP_H */
|
||||||
|
|||||||
@@ -49,6 +49,9 @@
|
|||||||
#include <linux/can.h>
|
#include <linux/can.h>
|
||||||
|
|
||||||
#define SOL_CAN_RAW (SOL_CAN_BASE + CAN_RAW)
|
#define SOL_CAN_RAW (SOL_CAN_BASE + CAN_RAW)
|
||||||
|
enum {
|
||||||
|
SCM_CAN_RAW_ERRQUEUE = 1,
|
||||||
|
};
|
||||||
|
|
||||||
/* for socket options affecting the socket (not the global system) */
|
/* for socket options affecting the socket (not the global system) */
|
||||||
|
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ struct nlmsghdr {
|
|||||||
(struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
|
(struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
|
||||||
#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \
|
#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \
|
||||||
(nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
|
(nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
|
||||||
(nlh)->nlmsg_len <= (len))
|
(int)((nlh)->nlmsg_len) <= (len))
|
||||||
#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
|
#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
|
||||||
|
|
||||||
#define NLMSG_NOOP 0x1 /* Nothing. */
|
#define NLMSG_NOOP 0x1 /* Nothing. */
|
||||||
|
|||||||
+30
-26
@@ -42,22 +42,23 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <libgen.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <libgen.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <linux/can.h>
|
#include <linux/can.h>
|
||||||
#include <linux/can/raw.h>
|
#include <linux/can/raw.h>
|
||||||
#include <linux/sockios.h>
|
#include <linux/sockios.h>
|
||||||
|
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
|
|
||||||
#define NO_CAN_ID 0xFFFFFFFFU
|
#define NO_CAN_ID 0xFFFFFFFFU
|
||||||
@@ -68,7 +69,8 @@ const int canfd_on = 1;
|
|||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "\nUsage: %s [options] <CAN interface>\n", prg);
|
fprintf(stderr, "\nUsage: %s [options] <CAN interface>\n", prg);
|
||||||
fprintf(stderr, "Options: -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
|
fprintf(stderr, "Options:\n");
|
||||||
|
fprintf(stderr, " -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
|
||||||
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
|
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
|
||||||
fprintf(stderr, " -x <addr> (extended addressing mode. Use 'any' for all addresses)\n");
|
fprintf(stderr, " -x <addr> (extended addressing mode. Use 'any' for all addresses)\n");
|
||||||
fprintf(stderr, " -X <addr> (extended addressing mode (rx addr). Use 'any' for all)\n");
|
fprintf(stderr, " -X <addr> (extended addressing mode (rx addr). Use 'any' for all)\n");
|
||||||
@@ -77,8 +79,10 @@ void print_usage(char *prg)
|
|||||||
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, " -u (print uds messages)\n");
|
fprintf(stderr, " -u (print uds messages)\n");
|
||||||
fprintf(stderr, "\nCAN IDs and addresses are given and expected in hexadecimal values.\n");
|
fprintf(stderr, "\nCAN IDs and addresses are given and expected in hexadecimal values.\n");
|
||||||
fprintf(stderr, "\nUDS output contains a flag which provides information about the type of the message.\n");
|
fprintf(stderr, "\nUDS output contains a flag which provides information about the type of the \n");
|
||||||
fprintf(stderr, "Flags: [SRQ] = Service Request\n");
|
fprintf(stderr, "message.\n\n");
|
||||||
|
fprintf(stderr, "Flags:\n");
|
||||||
|
fprintf(stderr, " [SRQ] = Service Request\n");
|
||||||
fprintf(stderr, " [PSR] = Positive Service Response\n");
|
fprintf(stderr, " [PSR] = Positive Service Response\n");
|
||||||
fprintf(stderr, " [NRC] = Negative Response Code\n");
|
fprintf(stderr, " [NRC] = Negative Response Code\n");
|
||||||
fprintf(stderr, " [???] = Unknown (not specified)\n");
|
fprintf(stderr, " [???] = Unknown (not specified)\n");
|
||||||
@@ -332,28 +336,28 @@ int main(int argc, char **argv)
|
|||||||
if (nbytes < 0) {
|
if (nbytes < 0) {
|
||||||
perror("read");
|
perror("read");
|
||||||
return 1;
|
return 1;
|
||||||
} else if (nbytes != CAN_MTU && nbytes != CANFD_MTU) {
|
}
|
||||||
|
if (nbytes != CAN_MTU && nbytes != CANFD_MTU) {
|
||||||
fprintf(stderr, "read: incomplete CAN frame %zu %d\n", sizeof(frame), nbytes);
|
fprintf(stderr, "read: incomplete CAN frame %zu %d\n", sizeof(frame), nbytes);
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
}
|
||||||
|
if (frame.can_id == src && ext && !extany &&
|
||||||
if (frame.can_id == src && ext && !extany && extaddr != frame.data[0])
|
extaddr != frame.data[0])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (frame.can_id == dst && rx_ext && !rx_extany && rx_extaddr != frame.data[0])
|
if (frame.can_id == dst && rx_ext && !rx_extany &&
|
||||||
|
rx_extaddr != frame.data[0])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (color)
|
if (color)
|
||||||
printf("%s", (frame.can_id == src)? FGRED:FGBLUE);
|
printf("%s", (frame.can_id == src) ? FGRED : FGBLUE);
|
||||||
|
|
||||||
if (timestamp) {
|
if (timestamp) {
|
||||||
ioctl(s, SIOCGSTAMP, &tv);
|
ioctl(s, SIOCGSTAMP, &tv);
|
||||||
|
|
||||||
|
|
||||||
switch (timestamp) {
|
switch (timestamp) {
|
||||||
|
|
||||||
case 'a': /* absolute with timestamp */
|
case 'a': /* absolute with timestamp */
|
||||||
printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
|
printf("(%lu.%06lu) ", tv.tv_sec, tv.tv_usec);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'A': /* absolute with date */
|
case 'A': /* absolute with date */
|
||||||
@@ -362,10 +366,10 @@ int main(int argc, char **argv)
|
|||||||
char timestring[25];
|
char timestring[25];
|
||||||
|
|
||||||
tm = *localtime(&tv.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",
|
||||||
printf("(%s.%06ld) ", timestring, tv.tv_usec);
|
&tm);
|
||||||
}
|
printf("(%s.%06lu) ", timestring, tv.tv_usec);
|
||||||
break;
|
} break;
|
||||||
|
|
||||||
case 'd': /* delta */
|
case 'd': /* delta */
|
||||||
case 'z': /* starting with zero */
|
case 'z': /* starting with zero */
|
||||||
@@ -380,12 +384,13 @@ int main(int argc, char **argv)
|
|||||||
diff.tv_sec--, diff.tv_usec += 1000000;
|
diff.tv_sec--, diff.tv_usec += 1000000;
|
||||||
if (diff.tv_sec < 0)
|
if (diff.tv_sec < 0)
|
||||||
diff.tv_sec = diff.tv_usec = 0;
|
diff.tv_sec = diff.tv_usec = 0;
|
||||||
printf("(%ld.%06ld) ", diff.tv_sec, diff.tv_usec);
|
printf("(%lu.%06lu) ", diff.tv_sec,
|
||||||
|
diff.tv_usec);
|
||||||
|
|
||||||
if (timestamp == 'd')
|
if (timestamp == 'd')
|
||||||
last_tv = tv; /* update for delta calculation */
|
last_tv =
|
||||||
}
|
tv; /* update for delta calculation */
|
||||||
break;
|
} break;
|
||||||
|
|
||||||
default: /* no timestamp output */
|
default: /* no timestamp output */
|
||||||
break;
|
break;
|
||||||
@@ -499,7 +504,6 @@ int main(int argc, char **argv)
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
close(s);
|
close(s);
|
||||||
|
|
||||||
|
|||||||
+18
-15
@@ -42,18 +42,18 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <libgen.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <linux/can.h>
|
#include <linux/can.h>
|
||||||
#include <linux/can/raw.h>
|
#include <linux/can/raw.h>
|
||||||
@@ -65,8 +65,10 @@
|
|||||||
|
|
||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
|
fprintf(stderr, "%s - ISO15765-2 protocol performance visualisation.\n", prg);
|
||||||
fprintf(stderr, "\nUsage: %s [options] <CAN interface>\n", prg);
|
fprintf(stderr, "\nUsage: %s [options] <CAN interface>\n", prg);
|
||||||
fprintf(stderr, "Options: -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
|
fprintf(stderr, "Options:\n");
|
||||||
|
fprintf(stderr, " -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
|
||||||
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
|
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
|
||||||
fprintf(stderr, " -x <addr> (extended addressing mode)\n");
|
fprintf(stderr, " -x <addr> (extended addressing mode)\n");
|
||||||
fprintf(stderr, " -X <addr> (extended addressing mode (rx addr))\n");
|
fprintf(stderr, " -X <addr> (extended addressing mode (rx addr))\n");
|
||||||
@@ -221,12 +223,14 @@ int main(int argc, char **argv)
|
|||||||
ret = nbytes;
|
ret = nbytes;
|
||||||
running = 0;
|
running = 0;
|
||||||
continue;
|
continue;
|
||||||
} else if (nbytes != CAN_MTU && nbytes != CANFD_MTU) {
|
}
|
||||||
|
if (nbytes != CAN_MTU && nbytes != CANFD_MTU) {
|
||||||
fprintf(stderr, "read: incomplete CAN frame %zu %d\n", sizeof(frame), nbytes);
|
fprintf(stderr, "read: incomplete CAN frame %zu %d\n", sizeof(frame), nbytes);
|
||||||
ret = nbytes;
|
ret = nbytes;
|
||||||
running = 0;
|
running = 0;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
if (rcvlen) {
|
if (rcvlen) {
|
||||||
/* make sure to process only the detected PDU CAN frame type */
|
/* make sure to process only the detected PDU CAN frame type */
|
||||||
if (canfd_on && (nbytes != CANFD_MTU))
|
if (canfd_on && (nbytes != CANFD_MTU))
|
||||||
@@ -247,11 +251,11 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
n_pci = frame.data[rx_ext];
|
n_pci = frame.data[rx_ext];
|
||||||
/* check flow control PCI only */
|
/* check flow control PCI only */
|
||||||
if ((n_pci & 0xF0) == 0x30) {
|
if ((n_pci & 0xF0) != 0x30)
|
||||||
bs = frame.data[rx_ext+1];
|
|
||||||
stmin = frame.data[rx_ext+2];
|
|
||||||
} else
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
bs = frame.data[rx_ext + 1];
|
||||||
|
stmin = frame.data[rx_ext + 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* data content starts and index datidx */
|
/* data content starts and index datidx */
|
||||||
@@ -363,7 +367,7 @@ int main(int argc, char **argv)
|
|||||||
percent = 100;
|
percent = 100;
|
||||||
|
|
||||||
for (i=0; i < NUMBAR; i++){
|
for (i=0; i < NUMBAR; i++){
|
||||||
if (i < percent/PERCENTRES)
|
if (i < (int)(percent/PERCENTRES))
|
||||||
printf("X");
|
printf("X");
|
||||||
else
|
else
|
||||||
printf(".");
|
printf(".");
|
||||||
@@ -395,7 +399,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
/* check devisor to be not zero */
|
/* check devisor to be not zero */
|
||||||
if (diff_tv.tv_sec * 1000 + diff_tv.tv_usec / 1000){
|
if (diff_tv.tv_sec * 1000 + diff_tv.tv_usec / 1000){
|
||||||
printf("%ld.%06lds ", diff_tv.tv_sec, diff_tv.tv_usec);
|
printf("%lu.%06lus ", diff_tv.tv_sec, diff_tv.tv_usec);
|
||||||
printf("=> %lu byte/s", (fflen * 1000) /
|
printf("=> %lu byte/s", (fflen * 1000) /
|
||||||
(diff_tv.tv_sec * 1000 + diff_tv.tv_usec / 1000));
|
(diff_tv.tv_sec * 1000 + diff_tv.tv_usec / 1000));
|
||||||
} else
|
} else
|
||||||
@@ -407,7 +411,6 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
close(s);
|
close(s);
|
||||||
|
|
||||||
|
|||||||
+6
-5
@@ -42,16 +42,16 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <libgen.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <libgen.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <linux/can.h>
|
#include <linux/can.h>
|
||||||
#include <linux/can/isotp.h>
|
#include <linux/can/isotp.h>
|
||||||
@@ -62,7 +62,8 @@
|
|||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "\nUsage: %s [options] <CAN interface>\n", prg);
|
fprintf(stderr, "\nUsage: %s [options] <CAN interface>\n", prg);
|
||||||
fprintf(stderr, "Options: -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
|
fprintf(stderr, "Options:\n");
|
||||||
|
fprintf(stderr, " -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
|
||||||
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
|
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
|
||||||
fprintf(stderr, " -x <addr>[:<rxaddr>] (extended addressing / opt. separate rxaddr)\n");
|
fprintf(stderr, " -x <addr>[:<rxaddr>] (extended addressing / opt. separate rxaddr)\n");
|
||||||
fprintf(stderr, " -p [tx]:[rx] (set and enable tx/rx padding bytes)\n");
|
fprintf(stderr, " -p [tx]:[rx] (set and enable tx/rx padding bytes)\n");
|
||||||
|
|||||||
+12
-6
@@ -42,16 +42,16 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <libgen.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <libgen.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <linux/can.h>
|
#include <linux/can.h>
|
||||||
#include <linux/can/isotp.h>
|
#include <linux/can/isotp.h>
|
||||||
@@ -62,7 +62,8 @@
|
|||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "\nUsage: %s [options] <CAN interface>\n", prg);
|
fprintf(stderr, "\nUsage: %s [options] <CAN interface>\n", prg);
|
||||||
fprintf(stderr, "Options: -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
|
fprintf(stderr, "Options:\n");
|
||||||
|
fprintf(stderr, " -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
|
||||||
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
|
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
|
||||||
fprintf(stderr, " -x <addr>[:<rxaddr>] (extended addressing / opt. separate rxaddr)\n");
|
fprintf(stderr, " -x <addr>[:<rxaddr>] (extended addressing / opt. separate rxaddr)\n");
|
||||||
fprintf(stderr, " -p [tx]:[rx] (set and enable tx/rx padding bytes)\n");
|
fprintf(stderr, " -p [tx]:[rx] (set and enable tx/rx padding bytes)\n");
|
||||||
@@ -70,6 +71,7 @@ void print_usage(char *prg)
|
|||||||
fprintf(stderr, " -t <time ns> (frame transmit time (N_As) in nanosecs)\n");
|
fprintf(stderr, " -t <time ns> (frame transmit time (N_As) in nanosecs)\n");
|
||||||
fprintf(stderr, " -f <time ns> (ignore FC and force local tx stmin value in nanosecs)\n");
|
fprintf(stderr, " -f <time ns> (ignore FC and force local tx stmin value in nanosecs)\n");
|
||||||
fprintf(stderr, " -D <len> (send a fixed PDU with len bytes - no STDIN data)\n");
|
fprintf(stderr, " -D <len> (send a fixed PDU with len bytes - no STDIN data)\n");
|
||||||
|
fprintf(stderr, " -b (block until the PDU transmission is completed)\n");
|
||||||
fprintf(stderr, " -L <mtu>:<tx_dl>:<tx_flags> (link layer options for CAN FD)\n");
|
fprintf(stderr, " -L <mtu>:<tx_dl>:<tx_flags> (link layer options for CAN FD)\n");
|
||||||
fprintf(stderr, "\nCAN IDs and addresses are given and expected in hexadecimal values.\n");
|
fprintf(stderr, "\nCAN IDs and addresses are given and expected in hexadecimal values.\n");
|
||||||
fprintf(stderr, "The pdu data is expected on STDIN in space separated ASCII hex values.\n");
|
fprintf(stderr, "The pdu data is expected on STDIN in space separated ASCII hex values.\n");
|
||||||
@@ -92,7 +94,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
addr.can_addr.tp.tx_id = addr.can_addr.tp.rx_id = NO_CAN_ID;
|
addr.can_addr.tp.tx_id = addr.can_addr.tp.rx_id = NO_CAN_ID;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "s:d:x:p:P:t:f:D:L:?")) != -1) {
|
while ((opt = getopt(argc, argv, "s:d:x:p:P:t:f:D:bL:?")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 's':
|
case 's':
|
||||||
addr.can_addr.tp.tx_id = strtoul(optarg, (char **)NULL, 16);
|
addr.can_addr.tp.tx_id = strtoul(optarg, (char **)NULL, 16);
|
||||||
@@ -175,6 +177,10 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'b':
|
||||||
|
opts.flags |= CAN_ISOTP_WAIT_TX_DONE;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'L':
|
case 'L':
|
||||||
if (sscanf(optarg, "%hhu:%hhu:%hhu",
|
if (sscanf(optarg, "%hhu:%hhu:%hhu",
|
||||||
&llopts.mtu,
|
&llopts.mtu,
|
||||||
|
|||||||
+25
-21
@@ -57,21 +57,22 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <libgen.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <signal.h>
|
#include <time.h>
|
||||||
#include <errno.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/uio.h>
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#include <linux/can.h>
|
#include <linux/can.h>
|
||||||
#include <linux/can/isotp.h>
|
#include <linux/can/isotp.h>
|
||||||
@@ -100,14 +101,13 @@ void childdied(int i)
|
|||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "\nUsage: %s -l <port> -s <can_id> -d <can_id> [options] <CAN interface>\n", prg);
|
fprintf(stderr, "\nUsage: %s -l <port> -s <can_id> -d <can_id> [options] <CAN interface>\n", prg);
|
||||||
fprintf(stderr, "Options: (* = mandatory)\n");
|
fprintf(stderr, "Options:\n");
|
||||||
fprintf(stderr, "\n");
|
|
||||||
fprintf(stderr, "ip addressing:\n");
|
fprintf(stderr, "ip addressing:\n");
|
||||||
fprintf(stderr, " * -l <port> (local port for the server)\n");
|
fprintf(stderr, " -l <port> * (local port for the server)\n");
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "isotp addressing:\n");
|
fprintf(stderr, "isotp addressing:\n");
|
||||||
fprintf(stderr, " * -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
|
fprintf(stderr, " -s <can_id> * (source can_id. Use 8 digits for extended IDs)\n");
|
||||||
fprintf(stderr, " * -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
|
fprintf(stderr, " -d <can_id> * (destination can_id. Use 8 digits for extended IDs)\n");
|
||||||
fprintf(stderr, " -x <addr>[:<rxaddr>] (extended addressing / opt. separate rxaddr)\n");
|
fprintf(stderr, " -x <addr>[:<rxaddr>] (extended addressing / opt. separate rxaddr)\n");
|
||||||
fprintf(stderr, " -L <mtu>:<tx_dl>:<tx_flags> (link layer options for CAN FD)\n");
|
fprintf(stderr, " -L <mtu>:<tx_dl>:<tx_flags> (link layer options for CAN FD)\n");
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
@@ -115,14 +115,16 @@ void print_usage(char *prg)
|
|||||||
fprintf(stderr, " -p [tx]:[rx] (set and enable tx/rx padding bytes)\n");
|
fprintf(stderr, " -p [tx]:[rx] (set and enable tx/rx padding bytes)\n");
|
||||||
fprintf(stderr, " -P <mode> (check rx padding for (l)ength (c)ontent (a)ll)\n");
|
fprintf(stderr, " -P <mode> (check rx padding for (l)ength (c)ontent (a)ll)\n");
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "rx path: (config, which is sent to the sender / data source)\n");
|
fprintf(stderr, "rx path:\n (config, which is sent to the sender / data source)\n");
|
||||||
fprintf(stderr, " -b <bs> (blocksize. 0 = off)\n");
|
fprintf(stderr, " -b <bs> (blocksize. 0 = off)\n");
|
||||||
fprintf(stderr, " -m <val> (STmin in ms/ns. See spec.)\n");
|
fprintf(stderr, " -m <val> (STmin in ms/ns. See spec.)\n");
|
||||||
fprintf(stderr, " -w <num> (max. wait frame transmissions)\n");
|
fprintf(stderr, " -w <num> (max. wait frame transmissions)\n");
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "tx path: (config, which changes local tx settings)\n");
|
fprintf(stderr, "tx path:\n (config, which changes local tx settings)\n");
|
||||||
fprintf(stderr, " -t <time ns> (transmit time in nanosecs)\n");
|
fprintf(stderr, " -t <time ns> (transmit time in nanosecs)\n");
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
|
fprintf(stderr, "(* = mandatory option)\n");
|
||||||
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "All values except for '-l' and '-t' are expected in hexadecimal values.\n");
|
fprintf(stderr, "All values except for '-l' and '-t' are expected in hexadecimal values.\n");
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
@@ -298,9 +300,13 @@ int main(int argc, char **argv)
|
|||||||
saddr.sin_port = htons(local_port);
|
saddr.sin_port = htons(local_port);
|
||||||
|
|
||||||
while(bind(sl,(struct sockaddr*)&saddr, sizeof(saddr)) < 0) {
|
while(bind(sl,(struct sockaddr*)&saddr, sizeof(saddr)) < 0) {
|
||||||
|
struct timespec f = {
|
||||||
|
.tv_nsec = 100 * 1000 * 1000,
|
||||||
|
};
|
||||||
|
|
||||||
printf(".");
|
printf(".");
|
||||||
fflush(NULL);
|
fflush(NULL);
|
||||||
usleep(100000);
|
nanosleep(&f, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listen(sl, 3) != 0) {
|
if (listen(sl, 3) != 0) {
|
||||||
@@ -311,11 +317,9 @@ int main(int argc, char **argv)
|
|||||||
while (1) {
|
while (1) {
|
||||||
sa = accept(sl,(struct sockaddr *)&clientaddr, &sin_size);
|
sa = accept(sl,(struct sockaddr *)&clientaddr, &sin_size);
|
||||||
if (sa > 0 ){
|
if (sa > 0 ){
|
||||||
|
if (!fork())
|
||||||
if (fork())
|
|
||||||
close(sa);
|
|
||||||
else
|
|
||||||
break;
|
break;
|
||||||
|
close(sa);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (errno != EINTR) {
|
if (errno != EINTR) {
|
||||||
|
|||||||
+11
-10
@@ -42,23 +42,23 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <libgen.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "terminal.h"
|
||||||
#include <linux/can.h>
|
#include <linux/can.h>
|
||||||
#include <linux/can/isotp.h>
|
#include <linux/can/isotp.h>
|
||||||
#include <linux/sockios.h>
|
#include <linux/sockios.h>
|
||||||
#include "terminal.h"
|
|
||||||
|
|
||||||
#define NO_CAN_ID 0xFFFFFFFFU
|
#define NO_CAN_ID 0xFFFFFFFFU
|
||||||
|
|
||||||
@@ -69,7 +69,8 @@
|
|||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "\nUsage: %s [options] <CAN interface>\n", prg);
|
fprintf(stderr, "\nUsage: %s [options] <CAN interface>\n", prg);
|
||||||
fprintf(stderr, "Options: -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
|
fprintf(stderr, "Options:\n");
|
||||||
|
fprintf(stderr, " -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
|
||||||
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
|
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
|
||||||
fprintf(stderr, " -x <addr> (extended addressing mode)\n");
|
fprintf(stderr, " -x <addr> (extended addressing mode)\n");
|
||||||
fprintf(stderr, " -X <addr> (extended addressing mode - rx addr)\n");
|
fprintf(stderr, " -X <addr> (extended addressing mode - rx addr)\n");
|
||||||
@@ -100,7 +101,7 @@ void printbuf(unsigned char *buffer, int nbytes, int color, int timestamp,
|
|||||||
switch (timestamp) {
|
switch (timestamp) {
|
||||||
|
|
||||||
case 'a': /* absolute with timestamp */
|
case 'a': /* absolute with timestamp */
|
||||||
printf("(%ld.%06ld) ", tv->tv_sec, tv->tv_usec);
|
printf("(%lu.%06lu) ", tv->tv_sec, tv->tv_usec);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'A': /* absolute with date */
|
case 'A': /* absolute with date */
|
||||||
@@ -110,7 +111,7 @@ void printbuf(unsigned char *buffer, int nbytes, int color, int timestamp,
|
|||||||
|
|
||||||
tm = *localtime(&tv->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);
|
||||||
printf("(%s.%06ld) ", timestring, tv->tv_usec);
|
printf("(%s.%06lu) ", timestring, tv->tv_usec);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -127,7 +128,7 @@ void printbuf(unsigned char *buffer, int nbytes, int color, int timestamp,
|
|||||||
diff.tv_sec--, diff.tv_usec += 1000000;
|
diff.tv_sec--, diff.tv_usec += 1000000;
|
||||||
if (diff.tv_sec < 0)
|
if (diff.tv_sec < 0)
|
||||||
diff.tv_sec = diff.tv_usec = 0;
|
diff.tv_sec = diff.tv_usec = 0;
|
||||||
printf("(%ld.%06ld) ", diff.tv_sec, diff.tv_usec);
|
printf("(%lu.%06lu) ", diff.tv_sec, diff.tv_usec);
|
||||||
|
|
||||||
if (timestamp == 'd')
|
if (timestamp == 'd')
|
||||||
*last_tv = *tv; /* update for delta calculation */
|
*last_tv = *tv; /* update for delta calculation */
|
||||||
|
|||||||
+11
-9
@@ -48,21 +48,21 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <libgen.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <libgen.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <linux/can.h>
|
#include <linux/can.h>
|
||||||
#include <linux/can/isotp.h>
|
#include <linux/can/isotp.h>
|
||||||
@@ -102,10 +102,12 @@ void perror_syslog(const char *s)
|
|||||||
|
|
||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
|
fprintf(stderr, "%s - IP over CAN ISO-TP (ISO15765-2) tunnel / proof-of-concept.\n", prg);
|
||||||
fprintf(stderr, "\nUsage: %s [options] <CAN interface>\n\n", prg);
|
fprintf(stderr, "\nUsage: %s [options] <CAN interface>\n\n", prg);
|
||||||
fprintf(stderr, "This program creates a Linux tunnel netdevice 'ctunX' and transfers the\n");
|
fprintf(stderr, "This program creates a Linux tunnel netdevice 'ctunX' and transfers the\n");
|
||||||
fprintf(stderr, "ethernet frames inside ISO15765-2 (unreliable) datagrams on CAN.\n\n");
|
fprintf(stderr, "ethernet frames inside ISO15765-2 (unreliable) datagrams on CAN.\n\n");
|
||||||
fprintf(stderr, "Options: -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
|
fprintf(stderr, "Options:\n");
|
||||||
|
fprintf(stderr, " -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
|
||||||
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
|
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
|
||||||
fprintf(stderr, " -n <name> (name of created IP netdevice. Default: '%s')\n", DEFAULT_NAME);
|
fprintf(stderr, " -n <name> (name of created IP netdevice. Default: '%s')\n", DEFAULT_NAME);
|
||||||
fprintf(stderr, " -x <addr>[:<rxaddr>] (extended addressing / opt. separate rxaddr)\n");
|
fprintf(stderr, " -x <addr>[:<rxaddr>] (extended addressing / opt. separate rxaddr)\n");
|
||||||
|
|||||||
+33
-31
@@ -10,29 +10,29 @@
|
|||||||
* as published by the Free Software Foundation
|
* as published by the Free Software Foundation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <inttypes.h>
|
||||||
#include <stdlib.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <sys/time.h>
|
#include <getopt.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <linux/can.h>
|
#include <linux/can.h>
|
||||||
#include <linux/can/j1939.h>
|
#include <linux/can/j1939.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "libj1939.h"
|
#include "libj1939.h"
|
||||||
|
|
||||||
static const char help_msg[] =
|
static const char help_msg[] =
|
||||||
"jacd: An SAE J1939 address claiming daemon" "\n"
|
"j1939acd: An SAE J1939 address claiming daemon" "\n"
|
||||||
"Usage: jacd [options] NAME [INTF]" "\n"
|
"Usage: j1939acd [options] NAME [INTF]" "\n"
|
||||||
"\n"
|
"Options:\n"
|
||||||
" -v, --verbose Increase verbosity" "\n"
|
" -v, --verbose Increase verbosity" "\n"
|
||||||
" -r, --range=RANGE Ranges of source addresses" "\n"
|
" -r, --range=RANGE Ranges of source addresses" "\n"
|
||||||
" e.g. 80,50-100,200-210 (defaults to 0-253)" "\n"
|
" e.g. 80,50-100,200-210 (defaults to 0-253)" "\n"
|
||||||
@@ -42,8 +42,9 @@ static const char help_msg[] =
|
|||||||
"\n"
|
"\n"
|
||||||
"NAME is the 64bit nodename" "\n"
|
"NAME is the 64bit nodename" "\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Example:" "\n"
|
"Examples:" "\n"
|
||||||
"jacd -r 100,80-120 -c /tmp/1122334455667788.jacd 1122334455667788" "\n"
|
"j1939acd -r 100,80-120 -c /tmp/1122334455667788.jacd 1122334455667788" "\n"
|
||||||
|
"j1939acd -r 100,80-120 -c /tmp/1122334455667788.jacd 1122334455667788 vcan0" "\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
#ifdef _GNU_SOURCE
|
#ifdef _GNU_SOURCE
|
||||||
@@ -182,7 +183,7 @@ static const struct j1939_filter filt[] = {
|
|||||||
.pgn = J1939_PGN_REQUEST,
|
.pgn = J1939_PGN_REQUEST,
|
||||||
.pgn_mask = J1939_PGN_PDU1_MAX,
|
.pgn_mask = J1939_PGN_PDU1_MAX,
|
||||||
}, {
|
}, {
|
||||||
.pgn = 0x0fed8,
|
.pgn = J1939_PGN_ADDRESS_COMMANDED,
|
||||||
.pgn_mask = J1939_PGN_MAX,
|
.pgn_mask = J1939_PGN_MAX,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -198,7 +199,7 @@ static int open_socket(const char *device, uint64_t name)
|
|||||||
.addr = J1939_IDLE_ADDR,
|
.addr = J1939_IDLE_ADDR,
|
||||||
.pgn = J1939_NO_PGN,
|
.pgn = J1939_NO_PGN,
|
||||||
},
|
},
|
||||||
.can_ifindex = if_nametoindex(s.intf),
|
.can_ifindex = if_nametoindex(device),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (s.verbose)
|
if (s.verbose)
|
||||||
@@ -251,7 +252,7 @@ static int repeat_address(int sock, uint64_t name)
|
|||||||
ret = sendto(sock, dat, sizeof(dat), 0, (const struct sockaddr *)&saddr,
|
ret = sendto(sock, dat, sizeof(dat), 0, (const struct sockaddr *)&saddr,
|
||||||
sizeof(saddr));
|
sizeof(saddr));
|
||||||
if (must_warn(ret))
|
if (must_warn(ret))
|
||||||
err(1, "send address claim for 0x%02x", s.last_sa);
|
fprintf(stderr, "send address claim for 0x%02x\n", s.last_sa);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
static int claim_address(int sock, uint64_t name, int sa)
|
static int claim_address(int sock, uint64_t name, int sa)
|
||||||
@@ -290,7 +291,7 @@ static int request_addresses(int sock)
|
|||||||
fprintf(stderr, "- sendto(, { 0, 0xee, 0, }, %zi, 0, %s, %zi);\n", sizeof(dat), libj1939_addr2str(&saddr), sizeof(saddr));
|
fprintf(stderr, "- sendto(, { 0, 0xee, 0, }, %zi, 0, %s, %zi);\n", sizeof(dat), libj1939_addr2str(&saddr), sizeof(saddr));
|
||||||
ret = sendto(sock, dat, sizeof(dat), 0, (void *)&saddr, sizeof(saddr));
|
ret = sendto(sock, dat, sizeof(dat), 0, (void *)&saddr, sizeof(saddr));
|
||||||
if (must_warn(ret))
|
if (must_warn(ret))
|
||||||
err(1, "send request for address claims");
|
fprintf(stdout, "send request for address claims");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,7 +365,7 @@ static void install_signal(int sig)
|
|||||||
static void schedule_itimer(int msec)
|
static void schedule_itimer(int msec)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct itimerval val = {};
|
struct itimerval val = { 0 };
|
||||||
|
|
||||||
val.it_value.tv_sec = msec / 1000;
|
val.it_value.tv_sec = msec / 1000;
|
||||||
val.it_value.tv_usec = (msec % 1000) * 1000;
|
val.it_value.tv_usec = (msec % 1000) * 1000;
|
||||||
@@ -382,9 +383,8 @@ static inline int addr_status_mine(int sa)
|
|||||||
{
|
{
|
||||||
if (sa == s.current_sa)
|
if (sa == s.current_sa)
|
||||||
return '*';
|
return '*';
|
||||||
else if (addr[sa].flags & F_USE)
|
if (addr[sa].flags & F_USE)
|
||||||
return '+';
|
return '+';
|
||||||
else
|
|
||||||
return '-';
|
return '-';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -486,7 +486,8 @@ int main(int argc, char *argv[])
|
|||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
#ifdef _GNU_SOURCE
|
#ifdef _GNU_SOURCE
|
||||||
if (asprintf(&program_invocation_name, "%s.%s", program_invocation_short_name, optarg) < 0)
|
if (asprintf(&program_invocation_name, "%s.%s",
|
||||||
|
program_invocation_short_name, optarg) < 0)
|
||||||
err(1, "asprintf(program invocation name)");
|
err(1, "asprintf(program invocation name)");
|
||||||
#else
|
#else
|
||||||
err(0, "compile with -D_GNU_SOURCE to use -p");
|
err(0, "compile with -D_GNU_SOURCE to use -p");
|
||||||
@@ -497,6 +498,7 @@ int main(int argc, char *argv[])
|
|||||||
exit(1);
|
exit(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argv[optind])
|
if (argv[optind])
|
||||||
s.name = strtoull(argv[optind++], 0, 16);
|
s.name = strtoull(argv[optind++], 0, 16);
|
||||||
if (argv[optind])
|
if (argv[optind])
|
||||||
@@ -512,12 +514,12 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
if ((s.current_sa < J1939_IDLE_ADDR) && !(addr[s.current_sa].flags & F_USE)) {
|
if ((s.current_sa < J1939_IDLE_ADDR) && !(addr[s.current_sa].flags & F_USE)) {
|
||||||
if (s.verbose)
|
if (s.verbose)
|
||||||
err(0, "forget saved address 0x%02x", s.current_sa);
|
fprintf(stderr, "- forget saved address 0x%02x\n", s.current_sa);
|
||||||
s.current_sa = J1939_IDLE_ADDR;
|
s.current_sa = J1939_IDLE_ADDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s.verbose)
|
if (s.verbose)
|
||||||
err(0, "ready for %s:%016llx", s.intf, (long long)s.name);
|
fprintf(stderr, "- ready for %s:%016llx\n", s.intf, (long long)s.name);
|
||||||
if (!s.intf || !s.name)
|
if (!s.intf || !s.name)
|
||||||
err(1, "bad arguments");
|
err(1, "bad arguments");
|
||||||
ret = sock = open_socket(s.intf, s.name);
|
ret = sock = open_socket(s.intf, s.name);
|
||||||
@@ -581,7 +583,7 @@ int main(int argc, char *argv[])
|
|||||||
break;
|
break;
|
||||||
if (s.state == STATE_REQ_SENT) {
|
if (s.state == STATE_REQ_SENT) {
|
||||||
if (s.verbose)
|
if (s.verbose)
|
||||||
err(0, "request sent, pending for 1250 ms");
|
fprintf(stderr, "- request sent, pending for 1250 ms\n");
|
||||||
schedule_itimer(1250);
|
schedule_itimer(1250);
|
||||||
s.state = STATE_REQ_PENDING;
|
s.state = STATE_REQ_PENDING;
|
||||||
} else if (s.state == STATE_OPERATIONAL) {
|
} else if (s.state == STATE_OPERATIONAL) {
|
||||||
@@ -611,14 +613,14 @@ int main(int argc, char *argv[])
|
|||||||
/* ourselves, disable itimer */
|
/* ourselves, disable itimer */
|
||||||
s.current_sa = sa;
|
s.current_sa = sa;
|
||||||
if (s.verbose)
|
if (s.verbose)
|
||||||
err(0, "claimed 0x%02x", sa);
|
fprintf(stderr, "- claimed 0x%02x\n", sa);
|
||||||
} else if (sa == s.current_sa) {
|
} else if (sa == s.current_sa) {
|
||||||
if (s.verbose)
|
if (s.verbose)
|
||||||
err(0, "address collision for 0x%02x", sa);
|
fprintf(stderr, "- address collision for 0x%02x\n", sa);
|
||||||
if (s.name > saddr.can_addr.j1939.name) {
|
if (s.name > saddr.can_addr.j1939.name) {
|
||||||
sa = choose_new_sa(s.name, sa);
|
sa = choose_new_sa(s.name, sa);
|
||||||
if (sa == J1939_IDLE_ADDR) {
|
if (sa == J1939_IDLE_ADDR) {
|
||||||
err(0, "no address left");
|
fprintf(stdout, "no address left");
|
||||||
/* put J1939_IDLE_ADDR in cache file */
|
/* put J1939_IDLE_ADDR in cache file */
|
||||||
s.current_sa = sa;
|
s.current_sa = sa;
|
||||||
goto done;
|
goto done;
|
||||||
@@ -629,7 +631,7 @@ int main(int argc, char *argv[])
|
|||||||
schedule_itimer(50);
|
schedule_itimer(50);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x0fed8:
|
case J1939_PGN_ADDRESS_COMMANDED:
|
||||||
if (!host_is_little_endian())
|
if (!host_is_little_endian())
|
||||||
bswap(dat, 8);
|
bswap(dat, 8);
|
||||||
memcpy(&cmd_name, dat, 8);
|
memcpy(&cmd_name, dat, 8);
|
||||||
@@ -643,7 +645,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
if (s.verbose)
|
if (s.verbose)
|
||||||
err(0, "shutdown");
|
fprintf(stderr, "- shutdown\n");
|
||||||
claim_address(sock, s.name, J1939_IDLE_ADDR);
|
claim_address(sock, s.name, J1939_IDLE_ADDR);
|
||||||
save_cache();
|
save_cache();
|
||||||
return 0;
|
return 0;
|
||||||
+88
-71
@@ -8,19 +8,20 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
|
#include <poll.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <poll.h>
|
|
||||||
|
|
||||||
#include <linux/errqueue.h>
|
#include <linux/errqueue.h>
|
||||||
#include <linux/netlink.h>
|
|
||||||
#include <linux/net_tstamp.h>
|
#include <linux/net_tstamp.h>
|
||||||
|
#include <linux/netlink.h>
|
||||||
#include <linux/socket.h>
|
#include <linux/socket.h>
|
||||||
|
|
||||||
#include "libj1939.h"
|
#include "libj1939.h"
|
||||||
|
|
||||||
#define J1939_MAX_ETP_PACKET_SIZE (7 * 0x00ffffff)
|
#define J1939_MAX_ETP_PACKET_SIZE (7 * 0x00ffffff)
|
||||||
#define JCAT_BUF_SIZE (1000 * 1024)
|
#define JCAT_BUF_SIZE (1000 * 1024)
|
||||||
|
|
||||||
@@ -36,13 +37,13 @@
|
|||||||
_min1 < _min2 ? _min1 : _min2; })
|
_min1 < _min2 ? _min1 : _min2; })
|
||||||
|
|
||||||
|
|
||||||
struct jcat_stats {
|
struct j1939cat_stats {
|
||||||
int err;
|
int err;
|
||||||
uint32_t tskey;
|
uint32_t tskey;
|
||||||
uint32_t send;
|
uint32_t send;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct jcat_priv {
|
struct j1939cat_priv {
|
||||||
int sock;
|
int sock;
|
||||||
int infile;
|
int infile;
|
||||||
int outfile;
|
int outfile;
|
||||||
@@ -55,6 +56,7 @@ struct jcat_priv {
|
|||||||
bool todo_recv;
|
bool todo_recv;
|
||||||
bool todo_filesize;
|
bool todo_filesize;
|
||||||
bool todo_connect;
|
bool todo_connect;
|
||||||
|
int todo_broadcast;
|
||||||
|
|
||||||
unsigned long polltimeout;
|
unsigned long polltimeout;
|
||||||
|
|
||||||
@@ -63,12 +65,12 @@ struct jcat_priv {
|
|||||||
|
|
||||||
struct sock_extended_err *serr;
|
struct sock_extended_err *serr;
|
||||||
struct scm_timestamping *tss;
|
struct scm_timestamping *tss;
|
||||||
struct jcat_stats stats;
|
struct j1939cat_stats stats;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char help_msg[] =
|
static const char help_msg[] =
|
||||||
"jcat: netcat tool for j1939\n"
|
"j1939cat: netcat-like tool for j1939\n"
|
||||||
"Usage: jcat FROM TO\n"
|
"Usage: j1939cat [options] FROM TO\n"
|
||||||
" FROM / TO - or [IFACE][:[SA][,[PGN][,NAME]]]\n"
|
" FROM / TO - or [IFACE][:[SA][,[PGN][,NAME]]]\n"
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
" -i <infile> (default stdin)\n"
|
" -i <infile> (default stdin)\n"
|
||||||
@@ -77,17 +79,18 @@ static const char help_msg[] =
|
|||||||
" -P <timeout> poll timeout in milliseconds before sending data.\n"
|
" -P <timeout> poll timeout in milliseconds before sending data.\n"
|
||||||
" With this option send() will be used with MSG_DONTWAIT flag.\n"
|
" With this option send() will be used with MSG_DONTWAIT flag.\n"
|
||||||
" -R <count> Set send repeat count. Default: 1\n"
|
" -R <count> Set send repeat count. Default: 1\n"
|
||||||
|
" -B Allow to send and receive broadcast packets.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Example:\n"
|
"Example:\n"
|
||||||
"jcat -i some_file_to_send can0:0x80 :0x90,0x12300\n"
|
"j1939cat -i some_file_to_send can0:0x80 :0x90,0x12300\n"
|
||||||
"jcat can0:0x90 -r > /tmp/some_file_to_receive\n"
|
"j1939cat can0:0x90 -r > /tmp/some_file_to_receive\n"
|
||||||
"\n"
|
"\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
static const char optstring[] = "?i:vs:rp:P:R:";
|
static const char optstring[] = "?hi:vs:rp:P:R:B";
|
||||||
|
|
||||||
|
|
||||||
static void jcat_init_sockaddr_can(struct sockaddr_can *sac)
|
static void j1939cat_init_sockaddr_can(struct sockaddr_can *sac)
|
||||||
{
|
{
|
||||||
sac->can_family = AF_CAN;
|
sac->can_family = AF_CAN;
|
||||||
sac->can_addr.j1939.addr = J1939_NO_ADDR;
|
sac->can_addr.j1939.addr = J1939_NO_ADDR;
|
||||||
@@ -95,7 +98,7 @@ static void jcat_init_sockaddr_can(struct sockaddr_can *sac)
|
|||||||
sac->can_addr.j1939.pgn = J1939_NO_PGN;
|
sac->can_addr.j1939.pgn = J1939_NO_PGN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t jcat_send_one(struct jcat_priv *priv, int out_fd,
|
static ssize_t j1939cat_send_one(struct j1939cat_priv *priv, int out_fd,
|
||||||
const void *buf, size_t buf_size)
|
const void *buf, size_t buf_size)
|
||||||
{
|
{
|
||||||
ssize_t num_sent;
|
ssize_t num_sent;
|
||||||
@@ -121,7 +124,7 @@ static ssize_t jcat_send_one(struct jcat_priv *priv, int out_fd,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_sent > buf_size) /* Should never happen */ {
|
if (num_sent > (ssize_t)buf_size) /* Should never happen */ {
|
||||||
warn("%s: send more then read", __func__);
|
warn("%s: send more then read", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -129,10 +132,10 @@ static ssize_t jcat_send_one(struct jcat_priv *priv, int out_fd,
|
|||||||
return num_sent;
|
return num_sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void jcat_print_timestamp(struct jcat_priv *priv, const char *name,
|
static void j1939cat_print_timestamp(struct j1939cat_priv *priv, const char *name,
|
||||||
struct timespec *cur)
|
struct timespec *cur)
|
||||||
{
|
{
|
||||||
struct jcat_stats *stats = &priv->stats;
|
struct j1939cat_stats *stats = &priv->stats;
|
||||||
|
|
||||||
if (!(cur->tv_sec | cur->tv_nsec))
|
if (!(cur->tv_sec | cur->tv_nsec))
|
||||||
return;
|
return;
|
||||||
@@ -144,7 +147,7 @@ static void jcat_print_timestamp(struct jcat_priv *priv, const char *name,
|
|||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *jcat_tstype_to_str(int tstype)
|
static const char *j1939cat_tstype_to_str(int tstype)
|
||||||
{
|
{
|
||||||
switch (tstype) {
|
switch (tstype) {
|
||||||
case SCM_TSTAMP_SCHED:
|
case SCM_TSTAMP_SCHED:
|
||||||
@@ -159,17 +162,17 @@ static const char *jcat_tstype_to_str(int tstype)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check the stats of SCM_TIMESTAMPING_OPT_STATS */
|
/* Check the stats of SCM_TIMESTAMPING_OPT_STATS */
|
||||||
static void jcat_scm_opt_stats(struct jcat_priv *priv, void *buf, int len)
|
static void j1939cat_scm_opt_stats(struct j1939cat_priv *priv, void *buf, int len)
|
||||||
{
|
{
|
||||||
struct jcat_stats *stats = &priv->stats;
|
struct j1939cat_stats *stats = &priv->stats;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
|
||||||
while (offset < len) {
|
while (offset < len) {
|
||||||
struct nlattr *nla = (struct nlattr *) (buf + offset);
|
struct nlattr *nla = (struct nlattr *) ((char *)buf + offset);
|
||||||
|
|
||||||
switch (nla->nla_type) {
|
switch (nla->nla_type) {
|
||||||
case J1939_NLA_BYTES_ACKED:
|
case J1939_NLA_BYTES_ACKED:
|
||||||
stats->send = *(uint32_t *)((void *)nla + NLA_HDRLEN);
|
stats->send = *(uint32_t *)((char *)nla + NLA_HDRLEN);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
warnx("not supported J1939_NLA field\n");
|
warnx("not supported J1939_NLA field\n");
|
||||||
@@ -179,9 +182,9 @@ static void jcat_scm_opt_stats(struct jcat_priv *priv, void *buf, int len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int jcat_extract_serr(struct jcat_priv *priv)
|
static int j1939cat_extract_serr(struct j1939cat_priv *priv)
|
||||||
{
|
{
|
||||||
struct jcat_stats *stats = &priv->stats;
|
struct j1939cat_stats *stats = &priv->stats;
|
||||||
struct sock_extended_err *serr = priv->serr;
|
struct sock_extended_err *serr = priv->serr;
|
||||||
struct scm_timestamping *tss = priv->tss;
|
struct scm_timestamping *tss = priv->tss;
|
||||||
|
|
||||||
@@ -205,12 +208,11 @@ static int jcat_extract_serr(struct jcat_priv *priv)
|
|||||||
serr->ee_errno);
|
serr->ee_errno);
|
||||||
stats->tskey = serr->ee_data;
|
stats->tskey = serr->ee_data;
|
||||||
|
|
||||||
jcat_print_timestamp(priv, jcat_tstype_to_str(serr->ee_info),
|
j1939cat_print_timestamp(priv, j1939cat_tstype_to_str(serr->ee_info),
|
||||||
&tss->ts[0]);
|
&tss->ts[0]);
|
||||||
|
|
||||||
if (serr->ee_info == SCM_TSTAMP_SCHED)
|
if (serr->ee_info == SCM_TSTAMP_SCHED)
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
else
|
|
||||||
return 0;
|
return 0;
|
||||||
case SO_EE_ORIGIN_LOCAL:
|
case SO_EE_ORIGIN_LOCAL:
|
||||||
/*
|
/*
|
||||||
@@ -232,7 +234,7 @@ static int jcat_extract_serr(struct jcat_priv *priv)
|
|||||||
warnx("serr: unknown ee_info: %i",
|
warnx("serr: unknown ee_info: %i",
|
||||||
serr->ee_info);
|
serr->ee_info);
|
||||||
|
|
||||||
jcat_print_timestamp(priv, " ABT", &tss->ts[0]);
|
j1939cat_print_timestamp(priv, " ABT", &tss->ts[0]);
|
||||||
warnx("serr: tx error: %i, %s", serr->ee_errno, strerror(serr->ee_errno));
|
warnx("serr: tx error: %i, %s", serr->ee_errno, strerror(serr->ee_errno));
|
||||||
|
|
||||||
return serr->ee_errno;
|
return serr->ee_errno;
|
||||||
@@ -243,7 +245,7 @@ static int jcat_extract_serr(struct jcat_priv *priv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int jcat_parse_cm(struct jcat_priv *priv, struct cmsghdr *cm)
|
static int j1939cat_parse_cm(struct j1939cat_priv *priv, struct cmsghdr *cm)
|
||||||
{
|
{
|
||||||
const size_t hdr_len = CMSG_ALIGN(sizeof(struct cmsghdr));
|
const size_t hdr_len = CMSG_ALIGN(sizeof(struct cmsghdr));
|
||||||
|
|
||||||
@@ -253,7 +255,7 @@ static int jcat_parse_cm(struct jcat_priv *priv, struct cmsghdr *cm)
|
|||||||
void *jstats = (void *)CMSG_DATA(cm);
|
void *jstats = (void *)CMSG_DATA(cm);
|
||||||
|
|
||||||
/* Activated with SOF_TIMESTAMPING_OPT_STATS */
|
/* Activated with SOF_TIMESTAMPING_OPT_STATS */
|
||||||
jcat_scm_opt_stats(priv, jstats, cm->cmsg_len - hdr_len);
|
j1939cat_scm_opt_stats(priv, jstats, cm->cmsg_len - hdr_len);
|
||||||
} else if (cm->cmsg_level == SOL_CAN_J1939 &&
|
} else if (cm->cmsg_level == SOL_CAN_J1939 &&
|
||||||
cm->cmsg_type == SCM_J1939_ERRQUEUE) {
|
cm->cmsg_type == SCM_J1939_ERRQUEUE) {
|
||||||
priv->serr = (void *)CMSG_DATA(cm);
|
priv->serr = (void *)CMSG_DATA(cm);
|
||||||
@@ -264,7 +266,7 @@ static int jcat_parse_cm(struct jcat_priv *priv, struct cmsghdr *cm)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int jcat_recv_err(struct jcat_priv *priv)
|
static int j1939cat_recv_err(struct j1939cat_priv *priv)
|
||||||
{
|
{
|
||||||
char control[100];
|
char control[100];
|
||||||
struct cmsghdr *cm;
|
struct cmsghdr *cm;
|
||||||
@@ -285,18 +287,18 @@ static int jcat_recv_err(struct jcat_priv *priv)
|
|||||||
|
|
||||||
for (cm = CMSG_FIRSTHDR(&msg); cm && cm->cmsg_len;
|
for (cm = CMSG_FIRSTHDR(&msg); cm && cm->cmsg_len;
|
||||||
cm = CMSG_NXTHDR(&msg, cm)) {
|
cm = CMSG_NXTHDR(&msg, cm)) {
|
||||||
jcat_parse_cm(priv, cm);
|
j1939cat_parse_cm(priv, cm);
|
||||||
if (priv->serr && priv->tss)
|
if (priv->serr && priv->tss)
|
||||||
return jcat_extract_serr(priv);
|
return j1939cat_extract_serr(priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int jcat_send_loop(struct jcat_priv *priv, int out_fd, char *buf,
|
static int j1939cat_send_loop(struct j1939cat_priv *priv, int out_fd, char *buf,
|
||||||
size_t buf_size)
|
size_t buf_size)
|
||||||
{
|
{
|
||||||
struct jcat_stats *stats = &priv->stats;
|
struct j1939cat_stats *stats = &priv->stats;
|
||||||
ssize_t count;
|
ssize_t count;
|
||||||
char *tmp_buf = buf;
|
char *tmp_buf = buf;
|
||||||
unsigned int events = POLLOUT | POLLERR;
|
unsigned int events = POLLOUT | POLLERR;
|
||||||
@@ -317,34 +319,32 @@ static int jcat_send_loop(struct jcat_priv *priv, int out_fd, char *buf,
|
|||||||
ret = poll(&fds, 1, priv->polltimeout);
|
ret = poll(&fds, 1, priv->polltimeout);
|
||||||
if (ret == -EINTR)
|
if (ret == -EINTR)
|
||||||
continue;
|
continue;
|
||||||
else if (ret < 0)
|
if (ret < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
else if (!ret)
|
if (!ret)
|
||||||
return -ETIME;
|
return -ETIME;
|
||||||
|
|
||||||
if (!(fds.revents & events)) {
|
if (!(fds.revents & events)) {
|
||||||
warn("%s: something else is wrong", __func__);
|
warn("%s: something else is wrong", __func__);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fds.revents & POLLERR) {
|
if (fds.revents & POLLERR) {
|
||||||
ret = jcat_recv_err(priv);
|
ret = j1939cat_recv_err(priv);
|
||||||
if (ret == -EINTR)
|
if (ret == -EINTR)
|
||||||
continue;
|
continue;
|
||||||
else if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
else if ((priv->repeat - 1) == stats->tskey)
|
if ((priv->repeat - 1) == stats->tskey)
|
||||||
tx_done = true;
|
tx_done = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fds.revents & POLLOUT) {
|
if (fds.revents & POLLOUT) {
|
||||||
num_sent = jcat_send_one(priv, out_fd, tmp_buf, count);
|
num_sent = j1939cat_send_one(priv, out_fd, tmp_buf, count);
|
||||||
if (num_sent < 0)
|
if (num_sent < 0)
|
||||||
return num_sent;
|
return num_sent;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
num_sent = jcat_send_one(priv, out_fd, tmp_buf, count);
|
num_sent = j1939cat_send_one(priv, out_fd, tmp_buf, count);
|
||||||
if (num_sent < 0)
|
if (num_sent < 0)
|
||||||
return num_sent;
|
return num_sent;
|
||||||
}
|
}
|
||||||
@@ -366,13 +366,14 @@ static int jcat_send_loop(struct jcat_priv *priv, int out_fd, char *buf,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int jcat_sendfile(struct jcat_priv *priv, int out_fd, int in_fd,
|
static int j1939cat_sendfile(struct j1939cat_priv *priv, int out_fd, int in_fd,
|
||||||
off_t *offset, size_t count)
|
off_t *offset, size_t count)
|
||||||
{
|
{
|
||||||
int ret = EXIT_SUCCESS;
|
int ret = EXIT_SUCCESS;
|
||||||
off_t orig = 0;
|
off_t orig = 0;
|
||||||
char *buf;
|
char *buf;
|
||||||
size_t to_read, num_read, buf_size;
|
ssize_t num_read;
|
||||||
|
size_t to_read, buf_size;
|
||||||
|
|
||||||
buf_size = min(priv->max_transfer, count);
|
buf_size = min(priv->max_transfer, count);
|
||||||
buf = malloc(buf_size);
|
buf = malloc(buf_size);
|
||||||
@@ -408,7 +409,7 @@ static int jcat_sendfile(struct jcat_priv *priv, int out_fd, int in_fd,
|
|||||||
if (num_read == 0)
|
if (num_read == 0)
|
||||||
break; /* EOF */
|
break; /* EOF */
|
||||||
|
|
||||||
ret = jcat_send_loop(priv, out_fd, buf, num_read);
|
ret = j1939cat_send_loop(priv, out_fd, buf, num_read);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto do_free;
|
goto do_free;
|
||||||
|
|
||||||
@@ -437,7 +438,7 @@ do_nofree:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t jcat_get_file_size(int fd)
|
static size_t j1939cat_get_file_size(int fd)
|
||||||
{
|
{
|
||||||
off_t offset;
|
off_t offset;
|
||||||
|
|
||||||
@@ -451,20 +452,21 @@ static size_t jcat_get_file_size(int fd)
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int jcat_send(struct jcat_priv *priv)
|
static int j1939cat_send(struct j1939cat_priv *priv)
|
||||||
{
|
{
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
int ret, i;
|
unsigned int i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (priv->todo_filesize)
|
if (priv->todo_filesize)
|
||||||
size = jcat_get_file_size(priv->infile);
|
size = j1939cat_get_file_size(priv->infile);
|
||||||
|
|
||||||
if (!size)
|
if (!size)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
for (i = 0; i < priv->repeat; i++) {
|
for (i = 0; i < priv->repeat; i++) {
|
||||||
priv->round++;
|
priv->round++;
|
||||||
ret = jcat_sendfile(priv, priv->sock, priv->infile, NULL, size);
|
ret = j1939cat_sendfile(priv, priv->sock, priv->infile, NULL, size);
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -475,7 +477,7 @@ static int jcat_send(struct jcat_priv *priv)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int jcat_recv_one(struct jcat_priv *priv, uint8_t *buf, size_t buf_size)
|
static int j1939cat_recv_one(struct j1939cat_priv *priv, uint8_t *buf, size_t buf_size)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@@ -494,7 +496,7 @@ static int jcat_recv_one(struct jcat_priv *priv, uint8_t *buf, size_t buf_size)
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int jcat_recv(struct jcat_priv *priv)
|
static int j1939cat_recv(struct j1939cat_priv *priv)
|
||||||
{
|
{
|
||||||
int ret = EXIT_SUCCESS;
|
int ret = EXIT_SUCCESS;
|
||||||
size_t buf_size;
|
size_t buf_size;
|
||||||
@@ -508,7 +510,7 @@ static int jcat_recv(struct jcat_priv *priv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (priv->todo_recv) {
|
while (priv->todo_recv) {
|
||||||
ret = jcat_recv_one(priv, buf, buf_size);
|
ret = j1939cat_recv_one(priv, buf, buf_size);
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -517,7 +519,7 @@ static int jcat_recv(struct jcat_priv *priv)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int jcat_sock_prepare(struct jcat_priv *priv)
|
static int j1939cat_sock_prepare(struct j1939cat_priv *priv)
|
||||||
{
|
{
|
||||||
unsigned int sock_opt;
|
unsigned int sock_opt;
|
||||||
int value;
|
int value;
|
||||||
@@ -558,6 +560,16 @@ static int jcat_sock_prepare(struct jcat_priv *priv)
|
|||||||
(char *) &sock_opt, sizeof(sock_opt)))
|
(char *) &sock_opt, sizeof(sock_opt)))
|
||||||
err(1, "setsockopt timestamping");
|
err(1, "setsockopt timestamping");
|
||||||
|
|
||||||
|
if (priv->todo_broadcast) {
|
||||||
|
ret = setsockopt(priv->sock, SOL_SOCKET, SO_BROADCAST,
|
||||||
|
&priv->todo_broadcast,
|
||||||
|
sizeof(priv->todo_broadcast));
|
||||||
|
if (ret < 0) {
|
||||||
|
warn("setsockopt: filed to set broadcast");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = bind(priv->sock, (void *)&priv->sockname, sizeof(priv->sockname));
|
ret = bind(priv->sock, (void *)&priv->sockname, sizeof(priv->sockname));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
warn("bind()");
|
warn("bind()");
|
||||||
@@ -581,7 +593,7 @@ static int jcat_sock_prepare(struct jcat_priv *priv)
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int jcat_parse_args(struct jcat_priv *priv, int argc, char *argv[])
|
static int j1939cat_parse_args(struct j1939cat_priv *priv, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int opt;
|
int opt;
|
||||||
|
|
||||||
@@ -597,8 +609,10 @@ static int jcat_parse_args(struct jcat_priv *priv, int argc, char *argv[])
|
|||||||
case 's':
|
case 's':
|
||||||
priv->max_transfer = strtoul(optarg, NULL, 0);
|
priv->max_transfer = strtoul(optarg, NULL, 0);
|
||||||
if (priv->max_transfer > J1939_MAX_ETP_PACKET_SIZE)
|
if (priv->max_transfer > J1939_MAX_ETP_PACKET_SIZE)
|
||||||
err(EXIT_FAILURE, "used value (%zu) is bigger then allowed maximal size: %u.\n",
|
err(EXIT_FAILURE,
|
||||||
priv->max_transfer, J1939_MAX_ETP_PACKET_SIZE);
|
"used value (%zu) is bigger then allowed maximal size: %u.\n",
|
||||||
|
priv->max_transfer,
|
||||||
|
J1939_MAX_ETP_PACKET_SIZE);
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
priv->todo_recv = 1;
|
priv->todo_recv = 1;
|
||||||
@@ -615,21 +629,26 @@ static int jcat_parse_args(struct jcat_priv *priv, int argc, char *argv[])
|
|||||||
case 'R':
|
case 'R':
|
||||||
priv->repeat = strtoul(optarg, NULL, 0);
|
priv->repeat = strtoul(optarg, NULL, 0);
|
||||||
if (priv->repeat < 1)
|
if (priv->repeat < 1)
|
||||||
err(EXIT_FAILURE, "send/repeat count can't be less then 1\n");
|
err(EXIT_FAILURE,
|
||||||
|
"send/repeat count can't be less then 1\n");
|
||||||
break;
|
break;
|
||||||
|
case 'B':
|
||||||
|
priv->todo_broadcast = 1;
|
||||||
|
break;
|
||||||
|
case 'h': /*fallthrough*/
|
||||||
default:
|
default:
|
||||||
fputs(help_msg, stderr);
|
fputs(help_msg, stderr);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argv[optind]) {
|
if (argv[optind]) {
|
||||||
if (strcmp("-", argv[optind]))
|
if (strcmp("-", argv[optind]) != 0)
|
||||||
libj1939_parse_canaddr(argv[optind], &priv->sockname);
|
libj1939_parse_canaddr(argv[optind], &priv->sockname);
|
||||||
optind++;
|
optind++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argv[optind]) {
|
if (argv[optind]) {
|
||||||
if (strcmp("-", argv[optind])) {
|
if (strcmp("-", argv[optind]) != 0) {
|
||||||
libj1939_parse_canaddr(argv[optind], &priv->peername);
|
libj1939_parse_canaddr(argv[optind], &priv->peername);
|
||||||
priv->valid_peername = 1;
|
priv->valid_peername = 1;
|
||||||
}
|
}
|
||||||
@@ -641,15 +660,13 @@ static int jcat_parse_args(struct jcat_priv *priv, int argc, char *argv[])
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct jcat_priv *priv;
|
struct j1939cat_priv *priv;
|
||||||
int ret;
|
int ret = 0;
|
||||||
|
|
||||||
priv = malloc(sizeof(*priv));
|
priv = calloc(1, sizeof(*priv));
|
||||||
if (!priv)
|
if (!priv)
|
||||||
err(EXIT_FAILURE, "can't allocate priv");
|
err(EXIT_FAILURE, "can't allocate priv");
|
||||||
|
|
||||||
bzero(priv, sizeof(*priv));
|
|
||||||
|
|
||||||
priv->todo_prio = -1;
|
priv->todo_prio = -1;
|
||||||
priv->infile = STDIN_FILENO;
|
priv->infile = STDIN_FILENO;
|
||||||
priv->outfile = STDOUT_FILENO;
|
priv->outfile = STDOUT_FILENO;
|
||||||
@@ -657,25 +674,25 @@ int main(int argc, char *argv[])
|
|||||||
priv->polltimeout = 100000;
|
priv->polltimeout = 100000;
|
||||||
priv->repeat = 1;
|
priv->repeat = 1;
|
||||||
|
|
||||||
jcat_init_sockaddr_can(&priv->sockname);
|
j1939cat_init_sockaddr_can(&priv->sockname);
|
||||||
jcat_init_sockaddr_can(&priv->peername);
|
j1939cat_init_sockaddr_can(&priv->peername);
|
||||||
|
|
||||||
ret = jcat_parse_args(priv, argc, argv);
|
ret = j1939cat_parse_args(priv, argc, argv);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = jcat_sock_prepare(priv);
|
ret = j1939cat_sock_prepare(priv);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (priv->todo_recv)
|
if (priv->todo_recv)
|
||||||
ret = jcat_recv(priv);
|
ret = j1939cat_recv(priv);
|
||||||
else
|
else
|
||||||
ret = jcat_send(priv);
|
ret = j1939cat_send(priv);
|
||||||
|
|
||||||
close(priv->infile);
|
close(priv->infile);
|
||||||
close(priv->outfile);
|
close(priv->outfile);
|
||||||
close(priv->sock);
|
close(priv->sock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
+16
-14
@@ -10,19 +10,19 @@
|
|||||||
* as published by the Free Software Foundation
|
* as published by the Free Software Foundation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <sys/socket.h>
|
#include <getopt.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "libj1939.h"
|
#include "libj1939.h"
|
||||||
|
|
||||||
@@ -30,9 +30,9 @@
|
|||||||
* getopt
|
* getopt
|
||||||
*/
|
*/
|
||||||
static const char help_msg[] =
|
static const char help_msg[] =
|
||||||
"jspy: An SAE J1939 spy utility" "\n"
|
"j1939spy: An SAE J1939 spy utility" "\n"
|
||||||
"Usage: jspy [OPTION...] [[IFACE:][NAME|SA][,PGN]]" "\n"
|
"Usage: j1939spy [OPTION...] [[IFACE:][NAME|SA][,PGN]]" "\n"
|
||||||
"\n"
|
"Options:\n"
|
||||||
" -v, --verbose Increase verbosity" "\n"
|
" -v, --verbose Increase verbosity" "\n"
|
||||||
" -P, --promisc Run in promiscuous mode" "\n"
|
" -P, --promisc Run in promiscuous mode" "\n"
|
||||||
" (= receive traffic not for this ECU)" "\n"
|
" (= receive traffic not for this ECU)" "\n"
|
||||||
@@ -95,8 +95,8 @@ static uint8_t *buf;
|
|||||||
*/
|
*/
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int ret, sock, j, opt;
|
int ret, sock, opt;
|
||||||
unsigned int len;
|
unsigned int j, len;
|
||||||
struct timeval tref, tdut, ttmp;
|
struct timeval tref, tdut, ttmp;
|
||||||
struct sockaddr_can src;
|
struct sockaddr_can src;
|
||||||
struct j1939_filter filt;
|
struct j1939_filter filt;
|
||||||
@@ -120,7 +120,8 @@ int main(int argc, char **argv)
|
|||||||
case 't':
|
case 't':
|
||||||
if (optarg) {
|
if (optarg) {
|
||||||
if (!strchr("adzA", optarg[0]))
|
if (!strchr("adzA", optarg[0]))
|
||||||
err(1, "unknown time option '%c'", optarg[0]);
|
err(1, "unknown time option '%c'",
|
||||||
|
optarg[0]);
|
||||||
s.time = optarg[0];
|
s.time = optarg[0];
|
||||||
} else {
|
} else {
|
||||||
s.time = 'z';
|
s.time = 'z';
|
||||||
@@ -131,6 +132,7 @@ int main(int argc, char **argv)
|
|||||||
exit(1);
|
exit(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argv[optind]) {
|
if (argv[optind]) {
|
||||||
optarg = argv[optind];
|
optarg = argv[optind];
|
||||||
ret = libj1939_str2addr(optarg, 0, &s.addr);
|
ret = libj1939_str2addr(optarg, 0, &s.addr);
|
||||||
@@ -287,7 +289,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
printf("[%i%s]", len, (msg.msg_flags & MSG_TRUNC) ? "..." : "");
|
printf("[%i%s]", len, (msg.msg_flags & MSG_TRUNC) ? "..." : "");
|
||||||
for (j = 0; j < len; ) {
|
for (j = 0; j < len; ) {
|
||||||
int end = j + 4;
|
unsigned int end = j + 4;
|
||||||
if (end > len)
|
if (end > len)
|
||||||
end = len;
|
end = len;
|
||||||
printf(" ");
|
printf(" ");
|
||||||
+10
-10
@@ -10,20 +10,20 @@
|
|||||||
* as published by the Free Software Foundation
|
* as published by the Free Software Foundation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
#include <getopt.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "libj1939.h"
|
#include "libj1939.h"
|
||||||
|
|
||||||
@@ -31,9 +31,9 @@
|
|||||||
* getopt
|
* getopt
|
||||||
*/
|
*/
|
||||||
static const char help_msg[] =
|
static const char help_msg[] =
|
||||||
"jsr: An SAE J1939 send/recv utility" "\n"
|
"j1939sr: An SAE J1939 send/recv utility" "\n"
|
||||||
"Usage: jsr [OPTION...] SOURCE [DEST]" "\n"
|
"Usage: j1939sr [OPTION...] SOURCE [DEST]" "\n"
|
||||||
"\n"
|
"Options:\n"
|
||||||
" -v, --verbose Increase verbosity" "\n"
|
" -v, --verbose Increase verbosity" "\n"
|
||||||
" -p, --priority=VAL J1939 priority (0..7, default 6)" "\n"
|
" -p, --priority=VAL J1939 priority (0..7, default 6)" "\n"
|
||||||
" -S, --serialize Strictly serialize outgoing packets" "\n"
|
" -S, --serialize Strictly serialize outgoing packets" "\n"
|
||||||
@@ -42,13 +42,13 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <sys/socket.h> /* for sa_family_t */
|
|
||||||
#include <linux/can.h>
|
#include <linux/can.h>
|
||||||
#include <linux/can/error.h>
|
#include <linux/can/error.h>
|
||||||
|
#include <sys/socket.h> /* for sa_family_t */
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
|
|
||||||
@@ -583,7 +583,7 @@ void snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *c
|
|||||||
if (!sep)
|
if (!sep)
|
||||||
sep = defsep;
|
sep = defsep;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(error_classes); i++) {
|
for (i = 0; i < (int)ARRAY_SIZE(error_classes); i++) {
|
||||||
mask = 1 << i;
|
mask = 1 << i;
|
||||||
if (class & mask) {
|
if (class & mask) {
|
||||||
if (classes)
|
if (classes)
|
||||||
|
|||||||
+7
-7
@@ -10,16 +10,16 @@
|
|||||||
* as published by the Free Software Foundation
|
* as published by the Free Software Foundation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ static const char *libj1939_ifnam(int ifindex)
|
|||||||
fetch_names();
|
fetch_names();
|
||||||
|
|
||||||
for (lp = saved; lp->if_index; ++lp) {
|
for (lp = saved; lp->if_index; ++lp) {
|
||||||
if (lp->if_index == ifindex)
|
if (lp->if_index == (unsigned int)ifindex)
|
||||||
return lp->if_name;
|
return lp->if_name;
|
||||||
}
|
}
|
||||||
if (cached) {
|
if (cached) {
|
||||||
@@ -64,7 +64,7 @@ static const char *libj1939_ifnam(int ifindex)
|
|||||||
*/
|
*/
|
||||||
libj1939_cleanup();
|
libj1939_cleanup();
|
||||||
return libj1939_ifnam(ifindex);
|
return libj1939_ifnam(ifindex);
|
||||||
} else
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ static int libj1939_ifindex(const char *str)
|
|||||||
if (cached) {
|
if (cached) {
|
||||||
libj1939_cleanup();
|
libj1939_cleanup();
|
||||||
return libj1939_ifindex(str);
|
return libj1939_ifindex(str);
|
||||||
} else
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,15 +42,15 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <libgen.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <libgen.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <linux/can.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <linux/can.h>
|
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
|
|
||||||
@@ -60,24 +60,119 @@ extern int optind, opterr, optopt;
|
|||||||
|
|
||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: %s [can-interfaces]\n", prg);
|
fprintf(stderr, "%s - convert compact CAN frame logfile to ASC logfile.\n", prg);
|
||||||
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
|
fprintf(stderr, "Usage: %s <options> [can-interfaces]\n", prg);
|
||||||
|
fprintf(stderr, "Options:\n");
|
||||||
|
fprintf(stderr, " -I <infile> (default stdin)\n");
|
||||||
fprintf(stderr, " -O <outfile> (default stdout)\n");
|
fprintf(stderr, " -O <outfile> (default stdout)\n");
|
||||||
fprintf(stderr, " -4 (reduce decimal place to 4 digits)\n");
|
fprintf(stderr, " -4 (reduce decimal place to 4 digits)\n");
|
||||||
fprintf(stderr, " -n (set newline to cr/lf - default lf)\n");
|
fprintf(stderr, " -n (set newline to cr/lf - default lf)\n");
|
||||||
|
fprintf(stderr, " -f (use CANFD format also for Classic CAN)\n");
|
||||||
|
fprintf(stderr, " -r (suppress dlc for RTR frames - pre v8.5 tools)\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void can_asc(struct canfd_frame *cf, int devno, int nortrdlc, char *extra_info, FILE *outfile)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char id[10];
|
||||||
|
char *dir = "Rx";
|
||||||
|
|
||||||
|
fprintf(outfile, "%-2d ", devno); /* channel number left aligned */
|
||||||
|
|
||||||
|
if (cf->can_id & CAN_ERR_FLAG)
|
||||||
|
fprintf(outfile, "ErrorFrame");
|
||||||
|
else {
|
||||||
|
sprintf(id, "%X%c", cf->can_id & CAN_EFF_MASK,
|
||||||
|
(cf->can_id & CAN_EFF_FLAG)?'x':' ');
|
||||||
|
|
||||||
|
/* check for extra info */
|
||||||
|
if (strlen(extra_info) > 0) {
|
||||||
|
/* only the first char is defined so far */
|
||||||
|
if (extra_info[0] == 'T')
|
||||||
|
dir = "Tx";
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(outfile, "%-15s %s ", id, dir);
|
||||||
|
|
||||||
|
if (cf->can_id & CAN_RTR_FLAG) {
|
||||||
|
if (nortrdlc)
|
||||||
|
fprintf(outfile, "r"); /* RTR frame */
|
||||||
|
else
|
||||||
|
fprintf(outfile, "r %d", cf->len); /* RTR frame */
|
||||||
|
} else {
|
||||||
|
fprintf(outfile, "d %d", cf->len); /* data frame */
|
||||||
|
|
||||||
|
for (i = 0; i < cf->len; i++) {
|
||||||
|
fprintf(outfile, " %02X", cf->data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void canfd_asc(struct canfd_frame *cf, int devno, int mtu, char *extra_info, FILE *outfile)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char id[10];
|
||||||
|
char *dir = "Rx";
|
||||||
|
unsigned int flags = 0;
|
||||||
|
unsigned int dlen = cf->len;
|
||||||
|
|
||||||
|
/* relevant flags in Flags field */
|
||||||
|
#define ASC_F_RTR 0x00000010
|
||||||
|
#define ASC_F_FDF 0x00001000
|
||||||
|
#define ASC_F_BRS 0x00002000
|
||||||
|
#define ASC_F_ESI 0x00004000
|
||||||
|
|
||||||
|
/* check for extra info */
|
||||||
|
if (strlen(extra_info) > 0) {
|
||||||
|
/* only the first char is defined so far */
|
||||||
|
if (extra_info[0] == 'T')
|
||||||
|
dir = "Tx";
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(outfile, "CANFD %3d %s ", devno, dir); /* 3 column channel number right aligned */
|
||||||
|
|
||||||
|
sprintf(id, "%X%c", cf->can_id & CAN_EFF_MASK,
|
||||||
|
(cf->can_id & CAN_EFF_FLAG)?'x':' ');
|
||||||
|
fprintf(outfile, "%11s ", id);
|
||||||
|
fprintf(outfile, "%c ", (cf->flags & CANFD_BRS)?'1':'0');
|
||||||
|
fprintf(outfile, "%c ", (cf->flags & CANFD_ESI)?'1':'0');
|
||||||
|
fprintf(outfile, "%x ", can_len2dlc(dlen));
|
||||||
|
|
||||||
|
if (mtu == CAN_MTU) {
|
||||||
|
if (cf->can_id & CAN_RTR_FLAG) {
|
||||||
|
/* no data length but dlc for RTR frames */
|
||||||
|
dlen = 0;
|
||||||
|
flags = ASC_F_RTR;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
flags = ASC_F_FDF;
|
||||||
|
if (cf->flags & CANFD_BRS)
|
||||||
|
flags |= ASC_F_BRS;
|
||||||
|
if (cf->flags & CANFD_ESI)
|
||||||
|
flags |= ASC_F_ESI;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(outfile, "%2d", dlen);
|
||||||
|
|
||||||
|
for (i = 0; i < (int)dlen; i++) {
|
||||||
|
fprintf(outfile, " %02X", cf->data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(outfile, " %8d %4d %8X 0 0 0 0 0", 130000, 130, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
static char buf[BUFSZ], device[BUFSZ], ascframe[BUFSZ], id[10];
|
static char buf[BUFSZ], device[BUFSZ], ascframe[BUFSZ], extra_info[BUFSZ];
|
||||||
|
|
||||||
struct canfd_frame cf;
|
struct canfd_frame cf;
|
||||||
static struct timeval tv, start_tv;
|
static struct timeval tv, start_tv;
|
||||||
FILE *infile = stdin;
|
FILE *infile = stdin;
|
||||||
FILE *outfile = stdout;
|
FILE *outfile = stdout;
|
||||||
static int maxdev, devno, i, crlf, d4, opt;
|
static int maxdev, devno, i, crlf, fdfmt, nortrdlc, d4, opt, mtu;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "I:O:4n?")) != -1) {
|
while ((opt = getopt(argc, argv, "I:O:4nfr?")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'I':
|
case 'I':
|
||||||
infile = fopen(optarg, "r");
|
infile = fopen(optarg, "r");
|
||||||
@@ -99,6 +194,14 @@ int main(int argc, char **argv)
|
|||||||
crlf = 1;
|
crlf = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
fdfmt = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'r':
|
||||||
|
nortrdlc = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case '4':
|
case '4':
|
||||||
d4 = 1;
|
d4 = 1;
|
||||||
break;
|
break;
|
||||||
@@ -137,11 +240,18 @@ int main(int argc, char **argv)
|
|||||||
if (buf[0] != '(')
|
if (buf[0] != '(')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (sscanf(buf, "(%ld.%ld) %s %s", &tv.tv_sec, &tv.tv_usec,
|
if (sscanf(buf, "(%lu.%lu) %s %s %s", &tv.tv_sec, &tv.tv_usec,
|
||||||
|
device, ascframe, extra_info) != 5) {
|
||||||
|
|
||||||
|
/* do not evaluate the extra info */
|
||||||
|
extra_info[0] = 0;
|
||||||
|
|
||||||
|
if (sscanf(buf, "(%lu.%lu) %s %s", &tv.tv_sec, &tv.tv_usec,
|
||||||
device, ascframe) != 4) {
|
device, ascframe) != 4) {
|
||||||
fprintf(stderr, "incorrect line format in logfile\n");
|
fprintf(stderr, "incorrect line format in logfile\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!start_tv.tv_sec) { /* print banner */
|
if (!start_tv.tv_sec) { /* print banner */
|
||||||
start_tv = tv;
|
start_tv = tv;
|
||||||
@@ -160,9 +270,14 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (devno) { /* only convert for selected CAN devices */
|
if (devno) { /* only convert for selected CAN devices */
|
||||||
if (parse_canframe(ascframe, &cf) != CAN_MTU) /* no CAN FD support so far */
|
mtu = parse_canframe(ascframe, &cf);
|
||||||
|
if ((mtu != CAN_MTU) && (mtu != CANFD_MTU))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
/* we don't support error message frames in CAN FD */
|
||||||
|
if ((mtu == CANFD_MTU) && (cf.can_id & CAN_ERR_FLAG))
|
||||||
|
continue;
|
||||||
|
|
||||||
tv.tv_sec = tv.tv_sec - start_tv.tv_sec;
|
tv.tv_sec = tv.tv_sec - start_tv.tv_sec;
|
||||||
tv.tv_usec = tv.tv_usec - start_tv.tv_usec;
|
tv.tv_usec = tv.tv_usec - start_tv.tv_usec;
|
||||||
if (tv.tv_usec < 0)
|
if (tv.tv_usec < 0)
|
||||||
@@ -171,29 +286,15 @@ int main(int argc, char **argv)
|
|||||||
tv.tv_sec = tv.tv_usec = 0;
|
tv.tv_sec = tv.tv_usec = 0;
|
||||||
|
|
||||||
if (d4)
|
if (d4)
|
||||||
fprintf(outfile, "%4ld.%04ld ", tv.tv_sec, tv.tv_usec/100);
|
fprintf(outfile, "%4lu.%04lu ", tv.tv_sec, tv.tv_usec/100);
|
||||||
else
|
else
|
||||||
fprintf(outfile, "%4ld.%06ld ", tv.tv_sec, tv.tv_usec);
|
fprintf(outfile, "%4lu.%06lu ", tv.tv_sec, tv.tv_usec);
|
||||||
|
|
||||||
fprintf(outfile, "%-2d ", devno); /* channel number left aligned */
|
if ((mtu == CAN_MTU) && (fdfmt == 0))
|
||||||
|
can_asc(&cf, devno, nortrdlc, extra_info, outfile);
|
||||||
|
else
|
||||||
|
canfd_asc(&cf, devno, mtu, extra_info, outfile);
|
||||||
|
|
||||||
if (cf.can_id & CAN_ERR_FLAG)
|
|
||||||
fprintf(outfile, "ErrorFrame");
|
|
||||||
else {
|
|
||||||
sprintf(id, "%X%c", cf.can_id & CAN_EFF_MASK,
|
|
||||||
(cf.can_id & CAN_EFF_FLAG)?'x':' ');
|
|
||||||
fprintf(outfile, "%-15s Rx ", id);
|
|
||||||
|
|
||||||
if (cf.can_id & CAN_RTR_FLAG)
|
|
||||||
fprintf(outfile, "r"); /* RTR frame */
|
|
||||||
else {
|
|
||||||
fprintf(outfile, "d %d", cf.len); /* data frame */
|
|
||||||
|
|
||||||
for (i = 0; i < cf.len; i++) {
|
|
||||||
fprintf(outfile, " %02X", cf.data[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (crlf)
|
if (crlf)
|
||||||
fprintf(outfile, "\r");
|
fprintf(outfile, "\r");
|
||||||
fprintf(outfile, "\n");
|
fprintf(outfile, "\n");
|
||||||
|
|||||||
+2
-2
@@ -44,15 +44,15 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <linux/can.h>
|
#include <linux/can.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
|
|
||||||
#define COMMENTSZ 200
|
#define COMMENTSZ 200
|
||||||
#define BUFSZ (sizeof("(1345212884.318850)") + IFNAMSIZ + 4 + CL_CFSZ + COMMENTSZ) /* for one line in the logfile */
|
#define BUFSZ (sizeof("(1345212884.318850)") + IFNAMSIZ + 4 + CL_CFSZ + COMMENTSZ) /* for one line in the logfile */
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(void)
|
||||||
{
|
{
|
||||||
char buf[BUFSZ], timestamp[BUFSZ], device[BUFSZ], ascframe[BUFSZ];
|
char buf[BUFSZ], timestamp[BUFSZ], device[BUFSZ], ascframe[BUFSZ];
|
||||||
struct canfd_frame cf;
|
struct canfd_frame cf;
|
||||||
|
|||||||
+14
-13
@@ -42,23 +42,25 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <linux/sockios.h>
|
||||||
|
#include <linux/tty.h>
|
||||||
|
#include <net/if.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <net/if.h>
|
#include <sys/socket.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <linux/tty.h>
|
#include <unistd.h>
|
||||||
#include <linux/sockios.h>
|
|
||||||
|
|
||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
|
fprintf(stderr, "%s - userspace tool for serial line CAN interface driver SLCAN.\n", prg);
|
||||||
fprintf(stderr, "\nUsage: %s [options] tty\n\n", prg);
|
fprintf(stderr, "\nUsage: %s [options] tty\n\n", prg);
|
||||||
fprintf(stderr, "Options: -o (send open command 'O\\r')\n");
|
fprintf(stderr, "Options:\n");
|
||||||
|
fprintf(stderr, " -o (send open command 'O\\r')\n");
|
||||||
fprintf(stderr, " -l (send listen only command 'L\\r', overrides -o)\n");
|
fprintf(stderr, " -l (send listen only command 'L\\r', overrides -o)\n");
|
||||||
fprintf(stderr, " -c (send close command 'C\\r')\n");
|
fprintf(stderr, " -c (send close command 'C\\r')\n");
|
||||||
fprintf(stderr, " -f (read status flags with 'F\\r' to reset error states)\n");
|
fprintf(stderr, " -f (read status flags with 'F\\r' to reset error states)\n");
|
||||||
@@ -68,11 +70,10 @@ void print_usage(char *prg)
|
|||||||
fprintf(stderr, " -w (attach - wait for keypess - detach)\n");
|
fprintf(stderr, " -w (attach - wait for keypess - detach)\n");
|
||||||
fprintf(stderr, " -n <name> (assign created netdevice name)\n");
|
fprintf(stderr, " -n <name> (assign created netdevice name)\n");
|
||||||
fprintf(stderr, "\nExamples:\n");
|
fprintf(stderr, "\nExamples:\n");
|
||||||
fprintf(stderr, "slcan_attach -w -o -f -s6 -c /dev/ttyS1\n");
|
fprintf(stderr, "slcan_attach -w -o -f -s6 -c /dev/ttyS1\n\n");
|
||||||
fprintf(stderr, "slcan_attach /dev/ttyS1\n");
|
fprintf(stderr, "slcan_attach /dev/ttyS1\n\n");
|
||||||
fprintf(stderr, "slcan_attach -d /dev/ttyS1\n");
|
fprintf(stderr, "slcan_attach -d /dev/ttyS1\n\n");
|
||||||
fprintf(stderr, "slcan_attach -w -n can15 /dev/ttyS1\n");
|
fprintf(stderr, "slcan_attach -w -n can15 /dev/ttyS1\n\n");
|
||||||
fprintf(stderr, "\n");
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,25 +22,25 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <linux/serial.h>
|
||||||
|
#include <linux/sockios.h>
|
||||||
|
#include <linux/tty.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <net/if.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <syslog.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <linux/tty.h>
|
#include <unistd.h>
|
||||||
#include <linux/sockios.h>
|
|
||||||
#include <linux/serial.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
/* Change this to whatever your daemon is called */
|
/* Change this to whatever your daemon is called */
|
||||||
#define DAEMON_NAME "slcand"
|
#define DAEMON_NAME "slcand"
|
||||||
@@ -72,8 +72,10 @@ static syslog_t syslogger = syslog;
|
|||||||
|
|
||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
{
|
{
|
||||||
|
fprintf(stderr, "%s - userspace daemon for serial line CAN interface driver SLCAN.\n", prg);
|
||||||
fprintf(stderr, "\nUsage: %s [options] <tty> [canif-name]\n\n", prg);
|
fprintf(stderr, "\nUsage: %s [options] <tty> [canif-name]\n\n", prg);
|
||||||
fprintf(stderr, "Options: -o (send open command 'O\\r')\n");
|
fprintf(stderr, "Options:\n");
|
||||||
|
fprintf(stderr, " -o (send open command 'O\\r')\n");
|
||||||
fprintf(stderr, " -c (send close command 'C\\r')\n");
|
fprintf(stderr, " -c (send close command 'C\\r')\n");
|
||||||
fprintf(stderr, " -f (read status flags with 'F\\r' to reset error states)\n");
|
fprintf(stderr, " -f (read status flags with 'F\\r' to reset error states)\n");
|
||||||
fprintf(stderr, " -l (send listen only command 'L\\r', overrides -o)\n");
|
fprintf(stderr, " -l (send listen only command 'L\\r', overrides -o)\n");
|
||||||
@@ -84,10 +86,9 @@ void print_usage(char *prg)
|
|||||||
fprintf(stderr, " -F (stay in foreground; no daemonize)\n");
|
fprintf(stderr, " -F (stay in foreground; no daemonize)\n");
|
||||||
fprintf(stderr, " -h (show this help page)\n");
|
fprintf(stderr, " -h (show this help page)\n");
|
||||||
fprintf(stderr, "\nExamples:\n");
|
fprintf(stderr, "\nExamples:\n");
|
||||||
fprintf(stderr, "slcand -o -c -f -s6 ttyUSB0\n");
|
fprintf(stderr, "slcand -o -c -f -s6 ttyUSB0\n\n");
|
||||||
fprintf(stderr, "slcand -o -c -f -s6 ttyUSB0 can0\n");
|
fprintf(stderr, "slcand -o -c -f -s6 ttyUSB0 can0\n\n");
|
||||||
fprintf(stderr, "slcand -o -c -f -s6 /dev/ttyUSB0\n");
|
fprintf(stderr, "slcand -o -c -f -s6 /dev/ttyUSB0\n\n");
|
||||||
fprintf(stderr, "\n");
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
-10
@@ -1,5 +1,7 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/*
|
/*
|
||||||
|
* slcanpty: adapter for applications using the slcan ASCII protocol
|
||||||
|
*
|
||||||
* slcanpty.c - creates a pty for applications using the slcan ASCII protocol
|
* slcanpty.c - creates a pty for applications using the slcan ASCII protocol
|
||||||
* and converts the ASCII data to a CAN network interface (and vice versa)
|
* and converts the ASCII data to a CAN network interface (and vice versa)
|
||||||
*
|
*
|
||||||
@@ -22,16 +24,18 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <libgen.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
@@ -428,16 +432,18 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
/* check command line options */
|
/* check command line options */
|
||||||
if (argc != 3) {
|
if (argc != 3) {
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "%s: adapter for applications using"
|
||||||
fprintf(stderr, "%s creates a pty for applications using"
|
" the slcan ASCII protocol.\n", basename(argv[0]));
|
||||||
" the slcan ASCII protocol and\n", argv[0]);
|
fprintf(stderr, "\n%s creates a pty for applications using"
|
||||||
|
" the slcan ASCII protocol and\n", basename(argv[0]));
|
||||||
fprintf(stderr, "converts the ASCII data to a CAN network"
|
fprintf(stderr, "converts the ASCII data to a CAN network"
|
||||||
" interface (and vice versa)\n\n");
|
" interface (and vice versa)\n\n");
|
||||||
fprintf(stderr, "Usage: %s <pty> <can interface>\n", argv[0]);
|
fprintf(stderr, "Usage: %s <pty> <can interface>\n", basename(argv[0]));
|
||||||
fprintf(stderr, "e.g. '%s /dev/ptyc0 can0' creates"
|
fprintf(stderr, "\nExamples:\n");
|
||||||
" /dev/ttyc0 for the slcan application\n", argv[0]);
|
fprintf(stderr, "%s /dev/ptyc0 can0 - creates /dev/ttyc0 for the slcan application\n\n",
|
||||||
|
basename(argv[0]));
|
||||||
fprintf(stderr, "e.g. for pseudo-terminal '%s %s can0' creates"
|
fprintf(stderr, "e.g. for pseudo-terminal '%s %s can0' creates"
|
||||||
" /dev/pts/N\n", argv[0], DEVICE_NAME_PTMX);
|
" /dev/pts/N\n", basename(argv[0]), DEVICE_NAME_PTMX);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-23
@@ -10,26 +10,26 @@
|
|||||||
* as published by the Free Software Foundation
|
* as published by the Free Software Foundation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <inttypes.h>
|
||||||
#include <stdlib.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <sys/time.h>
|
#include <getopt.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "libj1939.h"
|
#include "libj1939.h"
|
||||||
|
|
||||||
static const char help_msg[] =
|
static const char help_msg[] =
|
||||||
"testj1939: demonstrate j1939 use\n"
|
"testj1939: demonstrate j1939 use\n"
|
||||||
"Usage: testj1939 FROM TO\n"
|
"Usage: testj1939 [OPTIONS] FROM TO\n"
|
||||||
" FROM / TO - or [IFACE][:[SA][,[PGN][,NAME]]]\n"
|
" FROM / TO - or [IFACE][:[SA][,[PGN][,NAME]]]\n"
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
" -v Print relevant API calls\n"
|
" -v Print relevant API calls\n"
|
||||||
@@ -46,7 +46,7 @@ static const char help_msg[] =
|
|||||||
" -n Emit 64bit NAMEs in output\n"
|
" -n Emit 64bit NAMEs in output\n"
|
||||||
" -w[TIME] Return after TIME (default 1) seconds\n"
|
" -w[TIME] Return after TIME (default 1) seconds\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Example:\n"
|
"Examples:\n"
|
||||||
"testj1939 can1 20\n"
|
"testj1939 can1 20\n"
|
||||||
"\n"
|
"\n"
|
||||||
;
|
;
|
||||||
@@ -61,7 +61,7 @@ static void onsigalrm(int sig)
|
|||||||
|
|
||||||
static void schedule_oneshot_itimer(double delay)
|
static void schedule_oneshot_itimer(double delay)
|
||||||
{
|
{
|
||||||
struct itimerval it = {};
|
struct itimerval it = { 0 };
|
||||||
|
|
||||||
it.it_value.tv_sec = delay;
|
it.it_value.tv_sec = delay;
|
||||||
it.it_value.tv_usec = (long)(delay * 1e6) % 1000000;
|
it.it_value.tv_usec = (long)(delay * 1e6) % 1000000;
|
||||||
@@ -72,7 +72,8 @@ static void schedule_oneshot_itimer(double delay)
|
|||||||
/* main */
|
/* main */
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int ret, sock, opt, j;
|
int ret, sock, opt;
|
||||||
|
unsigned int j;
|
||||||
int verbose = 0;
|
int verbose = 0;
|
||||||
socklen_t peernamelen;
|
socklen_t peernamelen;
|
||||||
struct sockaddr_can sockname = {
|
struct sockaddr_can sockname = {
|
||||||
@@ -92,7 +93,8 @@ int main(int argc, char *argv[])
|
|||||||
};
|
};
|
||||||
uint8_t dat[128];
|
uint8_t dat[128];
|
||||||
int valid_peername = 0;
|
int valid_peername = 0;
|
||||||
int todo_send = 0, todo_recv = 0, todo_echo = 0, todo_prio = -1;
|
unsigned int todo_send = 0;
|
||||||
|
int todo_recv = 0, todo_echo = 0, todo_prio = -1;
|
||||||
int todo_connect = 0, todo_names = 0, todo_wait = 0, todo_rebind = 0;
|
int todo_connect = 0, todo_names = 0, todo_wait = 0, todo_rebind = 0;
|
||||||
int todo_broadcast = 0, todo_promisc = 0;
|
int todo_broadcast = 0, todo_promisc = 0;
|
||||||
int no_bind = 0;
|
int no_bind = 0;
|
||||||
@@ -106,7 +108,8 @@ int main(int argc, char *argv[])
|
|||||||
case 's':
|
case 's':
|
||||||
todo_send = strtoul(optarg ?: "8", NULL, 0);
|
todo_send = strtoul(optarg ?: "8", NULL, 0);
|
||||||
if (todo_send > sizeof(dat))
|
if (todo_send > sizeof(dat))
|
||||||
err(1, "Unsupported size. max: %zu", sizeof(dat));
|
err(1, "Unsupported size. max: %zu",
|
||||||
|
sizeof(dat));
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
todo_recv = 1;
|
todo_recv = 1;
|
||||||
@@ -147,7 +150,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (argv[optind]) {
|
if (argv[optind]) {
|
||||||
if (strcmp("-", argv[optind]))
|
if (strcmp("-", argv[optind]) != 0)
|
||||||
libj1939_parse_canaddr(argv[optind], &sockname);
|
libj1939_parse_canaddr(argv[optind], &sockname);
|
||||||
++optind;
|
++optind;
|
||||||
}
|
}
|
||||||
@@ -156,7 +159,7 @@ int main(int argc, char *argv[])
|
|||||||
sockname.can_addr.j1939.addr++;
|
sockname.can_addr.j1939.addr++;
|
||||||
|
|
||||||
if (argv[optind]) {
|
if (argv[optind]) {
|
||||||
if (strcmp("-", argv[optind])) {
|
if (strcmp("-", argv[optind]) != 0) {
|
||||||
libj1939_parse_canaddr(argv[optind], &peername);
|
libj1939_parse_canaddr(argv[optind], &peername);
|
||||||
valid_peername = 1;
|
valid_peername = 1;
|
||||||
}
|
}
|
||||||
@@ -289,18 +292,18 @@ int main(int argc, char *argv[])
|
|||||||
err(1, "sendto");
|
err(1, "sendto");
|
||||||
}
|
}
|
||||||
if (todo_recv) {
|
if (todo_recv) {
|
||||||
int i = 0;
|
int i;
|
||||||
|
|
||||||
if (todo_names && peername.can_addr.j1939.name)
|
if (todo_names && peername.can_addr.j1939.name)
|
||||||
printf("%016llx ", peername.can_addr.j1939.name);
|
printf("%016llx ", peername.can_addr.j1939.name);
|
||||||
printf("%02x %05x:", peername.can_addr.j1939.addr,
|
printf("%02x %05x:", peername.can_addr.j1939.addr,
|
||||||
peername.can_addr.j1939.pgn);
|
peername.can_addr.j1939.pgn);
|
||||||
for (j = 0; j < ret; ++j, i++) {
|
for (i = 0, j = 0; i < ret; ++i, j++) {
|
||||||
if (i == 8) {
|
if (j == 8) {
|
||||||
printf("\n%05x ", j);
|
printf("\n%05x ", i);
|
||||||
i = 0;
|
j = 0;
|
||||||
}
|
}
|
||||||
printf(" %02x", dat[j]);
|
printf(" %02x", dat[i]);
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user