327 Commits
Author SHA1 Message Date
Marc Kleine-BuddeandGitHub 856d0a662a Merge pull request #259 from marckleinebudde/cansequence
cansequence: do_send(): remove unneeded cast
2020-11-04 17:08:52 +01:00
Marc Kleine-Budde ccfa3c8b00 cansequence: do_send(): remove unneeded cast
This patch fixes the following warning:

cansequence.c:232:3: warning: expression result unused [-Wunused-value]
	(unsigned char)frame.data[0]++;
	^              ~~~~~~~~~~~~~~~

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-11-04 14:58:10 +01:00
Marc Kleine-BuddeandGitHub a6cac755b4 Merge pull request #258 from gibsson/master
Android.mk: remove duplicated cansequence definition
2020-11-04 14:57:44 +01:00
Gary Bisson 86bfa25f9d Android.mk: remove duplicated cansequence definition
Otherwise throwing the following error:
build/make/core/base_rules.mk:325: error: external/can-utils:
MODULE.TARGET.EXECUTABLES.cansequence already defined by
external/can-utils.

Fixes: a726c2a ("Merge branch 'cansequence' of
github.com:marckleinebudde/can-utils into master")

Signed-off-by: Gary Bisson <gary.bisson@boundarydevices.com>
2020-11-04 14:12:47 +01:00
Marc Kleine-BuddeandOliver Hartkopp 4573e852f9 log2asc: fix spelling
Fixes: 61dbb56ef6 ("log2asc: support DLC values in Classic CAN RTR frames")
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-10-19 20:52:05 +02:00
Marc Kleine-BuddeandGitHub 09466c2f1d Merge pull request #255 from marckleinebudde/ppc64le
travis: fix env for ppc64le
2020-10-19 15:00:41 +02:00
Marc Kleine-Budde eada3b4f53 travis: fix env for ppc64le
Fixes: b7ba7f32fc ("added script to run on power")
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-10-19 14:37:30 +02:00
Marc Kleine-BuddeandGitHub cb5d2fd653 Merge pull request #254 from marckleinebudde/cansequence
can-utils: import PTX cansequence utility
2020-10-19 14:35:04 +02:00
Marc Kleine-Budde a726c2a57a Merge branch 'cansequence' of github.com:marckleinebudde/can-utils into master
The PTX flavour canutils have a useful utility for generating a sequence of CAN
frames with an incrementing payload and checking such a sequence for missed and
reordered frames.

Recently, it has helped finding a regression in the kernel pfifo_fast qdisc,
which led to reordered frames.

To bring the utility to a greater audience, import the current state, including
its history, into the linux-can set of utilities.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-10-19 13:44:16 +02:00
Marc Kleine-Budde a8131b7996 cansequence: add SPDX identifier for GPL-2.0-only and copyrights
Message-Id: 20201019111239.GM12463@pengutronix.de
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-10-19 13:26:43 +02:00
Marc Kleine-BuddeandGitHub 93ef09d9b0 Merge pull request #242 from marckleinebudde/travis-ppc64le
travis: add ppc64le support
2020-10-15 18:36:19 +02:00
Marc Kleine-BuddeandGitHub 677f9ec26f Merge pull request #253 from marckleinebudde/fix-indention
Makefile: fix indention
2020-10-15 18:35:12 +02:00
Marc Kleine-Budde f3cf4cdf88 Makefile: fix indention
This patch fixes the indention, which was broken while renaming the j1939
tools.

Fixes: 8106214b55 ("Rename j* to j1939\1")
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-10-15 18:08:49 +02:00
Marc Kleine-Budde 2afcbd2fee cansequence: print error frames in hex
Fixes: faad20983348 ("cansequence: receive snd show error frames")
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-10-14 18:02:32 +02:00
Marc Kleine-Budde 00134246c2 cansequence.c: add extended identifier flag to mask
Without this, the extended identifier flag was not important when
filtering on CAN frames. Add this to mask to only receive the frame type
we want to recieve.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-10-14 18:02:32 +02:00
Marc Kleine-Budde a1c20aeb45 cansequence: receive snd show error frames
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-10-14 18:02:32 +02:00
Marc Kleine-Budde d699135833 cansequence: show delta and obsolute overflows
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-10-14 18:02:32 +02:00
Marc Kleine-Budde de5b9607dc cansequence: add internal 32 bit sequence counter 2020-10-14 18:02:32 +02:00
Marc Kleine-Budde 36fc75bdb7 cansequence: use sigaction() instead of signal
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-10-14 18:02:32 +02:00
Marc Kleine-Budde 68d5f87889 cansequence: exit with failure in case of unknown option
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-10-14 18:02:32 +02:00
Marc Kleine-Budde 4d50109a69 cansequence: do_receive: move variables into loop
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-10-14 18:02:32 +02:00
Marc Kleine-Budde ac9124c776 cansequence: sort options more alphabetically
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-10-14 18:02:32 +02:00
Marc Kleine-Budde 0bcb5d9c2c cansequence: codingstyle cleanups
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-10-14 18:02:32 +02:00
Marc Kleine-Budde 1e0fb39e8b cansequence: add support for drop after a certain number of incidents
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-10-14 18:02:32 +02:00
Marc Kleine-Budde 9567230494 cansequence: print out dropped packages by socket counter
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-10-14 18:02:30 +02:00
Marc Kleine-Budde 985121aaad cansequence: cleanup perror() and exit()
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-10-14 18:02:24 +02:00
Marc Kleine-Budde 7975f9859c cansequence: make use of bool variables
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-10-14 18:02:24 +02:00
Marc Kleine-Budde c9bb22022d cansequence: move rx and tx loop into separate functions
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-10-14 18:02:24 +02:00
Marc Kleine-Budde 2f125e44ce cansequence: mark functions as static
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-10-14 18:02:24 +02:00
Marc Kleine-Budde 9841820ea0 [cansequence] add sequence wrap around counter
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-10-14 18:02:24 +02:00
Marc Kleine-Budde fb5903f226 [cansequece] added various improvements
- added poll support if sender
- add cmd line option for can_id
- setup canfilter to disable receiving in sender mode

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-10-14 18:02:24 +02:00
Marc Kleine-Budde 4aaad29082 * src/cansequence.c:
obay loop option


git-svn-id: https://iocaste.extern.pengutronix.de/svn/canutils/trunks/canutils-3.0-trunk@104 5fd5a299-6ef2-0310-aa18-8b01d7c39d8c
2020-10-14 18:02:24 +02:00
Marc Kleine-Budde a16f8ed471 git-svn-id: https://iocaste.extern.pengutronix.de/svn/canutils/trunks/canutils-3.0-trunk@98 5fd5a299-6ef2-0310-aa18-8b01d7c39d8c 2020-10-14 18:02:24 +02:00
Marc Kleine-Budde 6e3b123d5b git-svn-id: https://iocaste.extern.pengutronix.de/svn/canutils/trunks/canutils-3.0-trunk@97 5fd5a299-6ef2-0310-aa18-8b01d7c39d8c 2020-10-14 18:02:20 +02:00
Marc Kleine-Budde c93d3a63c5 * src/cansequence.c, src/cansend.c:
fix interface cmd line

git-svn-id: https://iocaste.extern.pengutronix.de/svn/canutils/trunks/canutils-3.0-trunk@95 5fd5a299-6ef2-0310-aa18-8b01d7c39d8c
2020-10-14 18:02:10 +02:00
Marc Kleine-Budde 5fa35cbe2a git-svn-id: https://iocaste.extern.pengutronix.de/svn/canutils/trunks/canutils-3.0-trunk@92 5fd5a299-6ef2-0310-aa18-8b01d7c39d8c 2020-10-14 18:02:01 +02:00
Marc Kleine-Budde f4cec293dc git-svn-id: https://iocaste.extern.pengutronix.de/svn/canutils/trunks/canutils-3.0-trunk@91 5fd5a299-6ef2-0310-aa18-8b01d7c39d8c 2020-10-14 18:01:50 +02:00
Marc Kleine-Budde bd3ea25fe1 * src/cansequence.c, src/cansend.c:
cleanups

git-svn-id: https://iocaste.extern.pengutronix.de/svn/canutils/trunks/canutils-3.0-trunk@90 5fd5a299-6ef2-0310-aa18-8b01d7c39d8c
2020-10-14 18:01:48 +02:00
Marc Kleine-Budde d8be4d8a4f * src/canecho.c, src/candump.c, src/cansequence.c, src/cansend.c:
include limits.h

git-svn-id: https://iocaste.extern.pengutronix.de/svn/canutils/trunks/canutils-3.0-trunk@89 5fd5a299-6ef2-0310-aa18-8b01d7c39d8c
2020-10-14 18:01:37 +02:00
Marc Kleine-Budde b3b501d922 git-svn-id: https://iocaste.extern.pengutronix.de/svn/canutils/trunks/canutils-3.0-trunk@88 5fd5a299-6ef2-0310-aa18-8b01d7c39d8c 2020-10-14 18:01:23 +02:00
Marc Kleine-Budde 0c888d7942 * src/cansequence.c:
fixed print of received frame number


git-svn-id: https://iocaste.extern.pengutronix.de/svn/canutils/trunks/canutils-2.0-trunk@85 5fd5a299-6ef2-0310-aa18-8b01d7c39d8c
2020-10-14 18:00:36 +02:00
Marc Kleine-Budde ac8ae17727 * src/cansequence.c:
fixed out of order expected and received value


git-svn-id: https://iocaste.extern.pengutronix.de/svn/canutils/trunks/canutils-2.0-trunk@84 5fd5a299-6ef2-0310-aa18-8b01d7c39d8c
2020-10-14 18:00:36 +02:00
Marc Kleine-Budde 3794644caa git-svn-id: https://iocaste.extern.pengutronix.de/svn/canutils/trunks/canutils-2.0-trunk@71 5fd5a299-6ef2-0310-aa18-8b01d7c39d8c 2020-10-14 18:00:33 +02:00
Sascha HauerandMarc Kleine-Budde fc3b0449a9 use unsigned elements
git-svn-id: https://iocaste.extern.pengutronix.de/svn/canutils/trunks/canutils-1.0-trunk@49 5fd5a299-6ef2-0310-aa18-8b01d7c39d8c
2020-10-14 17:59:02 +02:00
Sascha HauerandMarc Kleine-Budde c55d181360 added twice verbose option
git-svn-id: https://iocaste.extern.pengutronix.de/svn/canutils/trunks/canutils-1.0-trunk@41 5fd5a299-6ef2-0310-aa18-8b01d7c39d8c
2020-10-14 17:59:02 +02:00
Sascha HauerandMarc Kleine-Budde d8435a56af add cansequence tool
git-svn-id: https://iocaste.extern.pengutronix.de/svn/canutils/trunks/canutils-1.0-trunk@40 5fd5a299-6ef2-0310-aa18-8b01d7c39d8c
2020-10-14 17:58:58 +02:00
Rosen PenevandOliver Hartkopp 204235c9ce make struct initialization C99 compatible again
Mainly change {} to { 0 } to remove a pedantic warning.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-10-14 13:29:13 +02:00
Oliver Hartkopp d3b29dfa48 includes: update to Linux 5.10 include files
- isotp.h: use latest version and formatting
- raw.h: introduce SCM_CAN_RAW_ERRQUEUE

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-10-14 09:28:22 +02:00
Oliver Hartkopp a591dadd96 cangw: fix sscanf() signed/unsigned warning
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-10-13 10:28:52 +02:00
Oliver Hartkopp 5e713b3ee0 cansniffer: remove obsolete semicolons
Silence compiler warning.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-10-13 10:16:52 +02:00
Oliver Hartkopp 5d5ccf38ee fix include order and unify local include placement
In commit https://github.com/linux-can/can-utils/commit/b153fe3f3591
("clang-tidy: sort includes alphabetically") the position of the "lib.h"
include has been moved in a way that struct canfd_frame has not been
defined anymore and lead to a warning when compiling cangen.c

This patch reverts that specific move and unifies the location of local
includes at the end of the include list.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-10-13 10:03:19 +02:00
Marc Kleine-BuddeandGitHub bda4b0ad8c Merge pull request #251 from neheb/clng
custom if statement reordering
2020-10-13 08:55:34 +02:00
Rosen Penev f766174677 custom if statement reordering
It makes more sense to return before hitting else.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-10-12 23:48:38 -07:00
Marc Kleine-BuddeandGitHub 7759b00c58 Merge pull request #250 from neheb/clng
clang-tidy fixes
2020-10-13 08:44:49 +02:00
Rosen Penev 48bb69bc7b remove basic usages of memset with {}
Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-10-12 23:28:58 -07:00
Rosen Penev b153fe3f35 clang-tidy: sort includes alphabetically
Found with llvm-include-order

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-10-12 23:28:58 -07:00
Rosen Penev 3e85fc5422 clang-tidy: fix cmp function usage
Found with bugprone-suspicious-string-compare

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-10-12 23:28:58 -07:00
Rosen Penev 33f3593436 clang-tidy: use uppercase literal
Found with readability-uppercase-literal-suffix

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-10-12 23:28:57 -07:00
Rosen Penev 3e67b5cbd1 clang-tidy: remove pointless return
Found with readability-redundant-control-flow

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-10-12 23:28:57 -07:00
Rosen Penev d5320d554e clang-tidy: fix wrong identation
Found with readability-misleading-indentation

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-10-12 23:28:57 -07:00
Rosen Penev 17a5fe6022 clang-tidy: do not use else after return
Found with readability-else-after-return

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-10-12 23:28:22 -07:00
Marc Kleine-BuddeandGitHub 5a93509655 Merge pull request #249 from neheb/nanosleep
convert usleep to nanosleep
2020-10-12 08:48:33 +02:00
Rosen Penev d7df79e687 convert usleep to nanosleep
usleep is removed in POSIX 2008.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-10-11 23:35:31 -07:00
Marc Kleine-BuddeandGitHub 18573d1dd2 Merge pull request #248 from neheb/bzr
j1939cat: remove bzero
2020-10-12 08:12:05 +02:00
Rosen Penev 8d2ed4c959 j1939cat: remove bzero
bzero is removed in POSIX 2008. malloc/bzero can also be replaced with
calloc.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-10-11 22:02:23 -07:00
c27c61424f can utils [can-j1939-install-kernel-module.md]: better explanation for adding backports, fixed typos and grammar (#247)
* Add tutorial how to compile kernel with can-j1939 module

* cosmetic changes

* improvement by adding debian backports to separate sources list

* better explanation for adding backports

* fixed typos

* fixed grammar

* improvement by adding debian backports to separate sources list

* better explanation for adding backports

* fixed typos

* fixed grammar

Co-authored-by: Zeljko Avramovic <avr0833@zelsd.rs>
2020-10-06 15:33:57 +02:00
zeljkoavramovicandGitHub 194959270f Added tutorial how to compile kernel with can-j1939 module (#246)
Add tutorial how to compile kernel with can-j1939 module
2020-10-05 16:15:08 +02:00
Oliver Hartkopp f6d963b5d9 isotpsend: add support for blocking write flag
With the new flag 'CAN_ISOTP_WAIT_TX_DONE' the send()/write() syscall returns
when the PDU is completely passed to the CAN netdevice queue. Depending on
STmin and other settings for the tx-queue-len this does not necessarily mean
that the PDU has been completely sent on the CAN interface at that time.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-10-01 20:42:50 +02:00
Marc Kleine-BuddeandGitHub 485d813545 Merge pull request #244 from marckleinebudde/canfdtest-check-device
canfdtest: bail out if trying to use non-existing CAN interface
2020-09-29 09:14:29 +02:00
Marc Kleine-Budde ce7f22928d canfdtest: bail out if trying to use non-existing CAN interface
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-09-29 09:06:12 +02:00
Marc Kleine-BuddeandGitHub dd8fb0b697 Merge pull request #241 from marckleinebudde/travis
travis: fix indention
2020-09-25 15:33:55 +02:00
genisysramandMarc Kleine-Budde b7ba7f32fc added script to run on power 2020-09-25 15:33:00 +02:00
Marc Kleine-Budde b99f540039 travis: add architecture marker
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-09-25 15:33:00 +02:00
Marc Kleine-Budde 7fb2585641 travis: fix indention
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-09-25 15:24:25 +02:00
Marc Kleine-BuddeandGitHub e1f75da433 Merge pull request #240 from marckleinebudde/canfdtest
canfdtest: remove trailing whitespace and print RX'ed frame in case of RX before TX
2020-09-24 11:27:10 +02:00
Marc Kleine-Budde 435a59a394 canfdtest: can_echo_gen(): print RX'ed frame in case of RX before TX
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-09-24 11:13:41 +02:00
Marc Kleine-Budde 73e421557f canfdtest: remove trailing whitespace
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-09-24 11:13:38 +02:00
Oleksij RempelandOliver Hartkopp ea844bdc5e Document J1939 commands
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2020-08-21 16:11:41 +02:00
Marc Kleine-BuddeandGitHub e6dfcb773e Merge pull request #237 from marckleinebudde/fix-canfdtest
canfdtest: fix frame consistency check
2020-08-20 09:33:11 +02:00
Marc Kleine-Budde c43a168c68 canfdtest: fix frame consistency check
This patch fixes the issue reported in:

https://github.com/linux-can/can-utils/commit/d7f28a0ffe36f73fe08729202f9c49ca5cac1dd4
https://github.com/linux-can/can-utils/issues/236

Reported-by: https://github.com/ronitnvidia
Fixes: d7f28a0ffe ("canfdtest: can_echo_dut(): check received frame for consistency")
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-08-20 09:30:27 +02:00
Oliver Hartkopp 7cb3e760fe logfile: add new extra info field
This patch adds a fourth string field in the can logfile format.
This new field contains the rx/tx direction information R/T as the
first entry (only one character separated from the CAN frame by space).

To generate the logfile format with this extra field candump has to be
called with the '-x' option for extra message infos,
e.g. 'candump -x -l can0' or 'candump -x -L can0'

log2asc and asc2log are extended to support the direction information
but still support the previous format without direction information.

The format extension does not affect legacy tools, e.g. the existing
canplayer ignores this extra information and does not need to be changed.

Therefore the existing logfiles remain valid and usable.

The extra message infos will be colon separated when there's need for
additional content beyond the rx/tx direction information, e.g. R:xx:yyy

Suggested-by: Pallavi Revanna https://github.com/brpallu
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-08-18 13:29:36 +02:00
Oliver Hartkopp a4905ed7c8 fix timeval to ASCII unsigned value conversion
As reported by Oleksij Rempel here
https://github.com/linux-can/can-utils/issues/233#issuecomment-674818935
the representation of timeval timestamps are signed values which leads to
negative values on 32 bit machines addressing the year 2038 unix sec counter
overflow.

Fix the issue on 32 bit systems by converting the timeval values to unsigned
ASCII value representations.

Fixes: https://github.com/linux-can/can-utils/issues/234
Reported-by: Oleksij Rempel <o.rempel@pengutronix.de>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-08-18 12:51:35 +02:00
Marc Kleine-BuddeandGitHub ab23c6f7e7 Merge pull request #232 from olerem/testj1939
testj1939: print proper offset in the data damp
2020-08-07 15:06:36 +02:00
Oleksij Rempel c912d6f8d5 testj1939: print proper offset in the data damp
without this patch we will always print "0008" on each line

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2020-08-07 15:01:43 +02:00
Marc Kleine-BuddeandGitHub 58dc257e11 Merge pull request #231 from olerem/jcat-bam
j1939cat: add broadcast support
2020-08-07 14:23:46 +02:00
Oleksij Rempel 327587b2c8 j1939cat: add broadcast support
Allow to use j1939cat to send and receive broadcast (TP.BAM) messages.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2020-08-07 14:14:38 +02:00
Marc Kleine-BuddeandGitHub 659e0acfe6 Merge pull request #230 from marckleinebudde/j1939acd
j1939acd help text improvements
2020-08-07 14:10:29 +02:00
josemicandMarc Kleine-Budde 88ad7e5755 j1939acd: add example showing optional interface parameter
Changed j1939acd help examples by adding one example showing optional interface
parameter.
2020-08-07 14:01:34 +02:00
josemicandMarc Kleine-Budde 112421dc22 j1939acd: fix help examples
Changed j1939acd help examples by removing duplicate example.

Fixes: 506252e9bc ("jacd.c: Reformat help/usage output to be compatible with help2man.")
2020-08-07 14:00:57 +02:00
Marc Kleine-BuddeandGitHub dec3c5eda1 Merge pull request #225 from marckleinebudde/fix-warnings
Fix warnings
2020-08-07 13:53:48 +02:00
Marc Kleine-BuddeandGitHub bad90515f0 Merge pull request #229 from joseogandoj/patch-1
Update testj1939.c
2020-07-31 08:21:17 +02:00
joseogandojandGitHub da87d595c5 Update testj1939.c
When receiving multi chunk messages, only the first 8 are printed.

Simple coding mistake. Should print dat[i] instead of dat[j]
2020-07-30 16:21:45 -05:00
Göran MannbergandOliver Hartkopp af531c3d52 Update Android.mk
Fixed typo in LOCAL_MODULE isotpsniffer
2020-07-06 08:47:35 +02:00
Marc Kleine-Budde 8e3c050b1c CMakeLists.txt: update test for _GNU_SOURCE to fix warnings
../asc2log.c:264:8: warning: implicit declaration of function 'strcasestr' is invalid in C99 [-Wimplicit-function-declaration]
        ptr = strcasestr(buf, tmp1);
              ^
../asc2log.c:264:6: warning: incompatible integer to pointer conversion assigning to 'char *' from 'int' [-Wint-conversion]
        ptr = strcasestr(buf, tmp1);
            ^ ~~~~~~~~~~~~~~~~~~~~~
../asc2log.c:328:6: warning: implicit declaration of function 'strcasestr' is invalid in C99 [-Wimplicit-function-declaration]
        if (strcasestr(date, " pm ") != NULL) {
            ^
../asc2log.c:328:31: warning: comparison between pointer and integer ('int' and 'void *') [-Wpointer-integer-compare]
        if (strcasestr(date, " pm ") != NULL) {
            ~~~~~~~~~~~~~~~~~~~~~~~~ ^  ~~~~
../asc2log.c:336:8: warning: implicit declaration of function 'strptime' is invalid in C99 [-Wimplicit-function-declaration]
                if (!strptime(date, "%B %d %I:%M:%S %p %Y", &tms)) {
                     ^
../asc2log.c:354:8: warning: implicit declaration of function 'strptime' is invalid in C99 [-Wimplicit-function-declaration]
                if (!strptime(date, "%B %d %H:%M:%S %Y", &tms)) {

../slcanpty.c:476:7: warning: implicit declaration of function 'grantpt' is invalid in C99 [-Wimplicit-function-declaration]
                if (grantpt(p) < 0) {
                    ^
../slcanpty.c:481:7: warning: implicit declaration of function 'unlockpt' is invalid in C99 [-Wimplicit-function-declaration]
                if (unlockpt(p) < 0) {
                    ^
../slcanpty.c:486:14: warning: implicit declaration of function 'ptsname' is invalid in C99 [-Wimplicit-function-declaration]
                name_pts = ptsname(p);
                           ^
../slcanpty.c:486:12: warning: incompatible integer to pointer conversion assigning to 'char *' from 'int' [-Wint-conversion]
                name_pts = ptsname(p);
                         ^ ~~~~~~~~~~

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-06-29 18:20:18 +02:00
Marc Kleine-Budde a5c049d37a slcanpty: add missing include sys/select.h
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-06-29 18:20:18 +02:00
Marc Kleine-Budde 57949154cc slcanpty: sort includes alphabetically
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-06-29 18:20:11 +02:00
Marc Kleine-BuddeandGitHub 24b73044c5 Merge pull request #224 from marckleinebudde/canfdtest
Canfdtest
2020-06-29 18:18:18 +02:00
Marc Kleine-Budde b29a75d4c6 j1939cat: j1939cat_parse_args(): fix warning
although it looks like a false positive:

/home/travis/build/linux-can/can-utils/j1939cat.c: In function ‘main’:
/home/travis/build/linux-can/can-utils/j1939cat.c:648:6: warning: ‘ret’ may be used uninitialized in this function [-Wmaybe-uninitialized]
  int ret;
      ^

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-06-22 12:41:48 +02:00
Marc Kleine-Budde 0f9c69c193 can-calc-bit-timing: fix warning
although it looks like a false positive:

/home/travis/build/linux-can/can-utils/can-calc-bit-timing.c: In function ‘print_bit_timing.isra.6’:
/home/travis/build/linux-can/can-utils/can-calc-bit-timing.c:447:42: warning: ‘tseg2’ may be used uninitialized in this function [-Wmaybe-uninitialized]
  unsigned int brp, tsegall, tseg, tseg1, tseg2;
                                          ^
/home/travis/build/linux-can/can-utils/can-calc-bit-timing.c:447:35: warning: ‘tseg1’ may be used uninitialized in this function [-Wmaybe-uninitialized]
  unsigned int brp, tsegall, tseg, tseg1, tseg2;
                                   ^

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-06-22 12:41:48 +02:00
Marc Kleine-Budde 13ecaa6d7e canfdtest: make number of frames in flight a command line option
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-06-22 11:59:35 +02:00
Marc Kleine-Budde d7f28a0ffe canfdtest: can_echo_dut(): check received frame for consistency
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-06-22 11:38:48 +02:00
Marc Kleine-Budde e393697112 canfdtest: can_echo_dut(): move functionality to increment frame data into separate function
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-06-22 11:38:48 +02:00
Marc Kleine-Budde 645cd1b1ba canfdtest: can_echo_dut(): make use of print_frame() instead of open coding it
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-06-22 11:38:48 +02:00
Marc Kleine-Budde aa5386f1cb canfdtest: print_frame(): add missing cast to uint8_t to avoid overruns
While there, use cast in compare_frame(), too.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-06-22 11:38:48 +02:00
Marc Kleine-Budde ff3d0e0d05 canfdtest: print_frame()/print_compare(): mark parameters "struct can_frame *" as const
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-06-22 11:38:17 +02:00
Marc Kleine-Budde 29605e3314 canfdtest: compare_frame(): remove stray space in front of "!"
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-06-22 11:26:03 +02:00
Marc Kleine-Budde d92adf68e8 canfdtest: main(): remove double ";"
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-06-22 11:25:21 +02:00
Marc Kleine-BuddeandGitHub 063e361cc5 Merge pull request #194 from marckleinebudde/canfdtest-initialize-tx_frames
canfdtest: can_echo_gen(): initialize tx_frames with zero
2020-06-17 12:53:32 +02:00
Marc Kleine-BuddeandGitHub e9e1a02085 Merge pull request #223 from marckleinebudde/jacd
j1939acd: replace 0x0fed8 by constant J1939_PGN_ADDRESS_COMMANDED
2020-06-17 12:51:32 +02:00
Marc Kleine-Budde 19b3ffe34b j1939acd: replace 0x0fed8 by constant J1939_PGN_ADDRESS_COMMANDED
Reported-by: josemic <josemic@users.noreply.github.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-06-17 12:37:30 +02:00
Marc Kleine-BuddeandGitHub 6553ccaf06 Merge pull request #221 from josemic/patch-4
Changed hardcoded hex number 0x0fed8 to j1939.h constant "J1939_PGN_ADDRESS_COMMANDED"
2020-06-17 12:34:51 +02:00
josemicandGitHub 1b5d3adbe5 Changed hardcoded hex number 0x0fed8 to j1939.h constant "J1939_PGN_ADDRESS_COMMANDED"
Use include constant instead of hardcoded constant
2020-06-17 10:54:46 +02:00
Marc Kleine-BuddeandGitHub e15b044a1d Merge pull request #220 from olerem/j1939acd-verbose
J1939acd verbose
2020-06-16 14:35:57 +02:00
Oliver Hartkopp 669fa79b21 j1939: Fix arithmetic on a pointer warning
Fix missing (recently introduced) j1939 files that have not been fixed
in commit 43610bd621 ("Fix arithmetic on a pointer warning") from
Gary Bisson.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-06-12 20:08:18 +02:00
Oliver Hartkopp 75d9c7e95f j1939: Fix comparison type mismatch warnings
Fix missing (recently introduced) j1939 files that have not been fixed
in commit 46895a41c5 ("Fix comparison type mismatch warnings") from
Gary Bisson.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-06-12 20:08:18 +02:00
Oliver Hartkopp 85ae5aaecf j1939acd: fix unused variable warning
open_socket() has a parameter to provide a network device name which
is properly assigned by its callers to s.intf in main().
Instead of using the callers value open_socket() directly accesses the
global s.intf which generates an unused variable warning with clang.

Fix this by using the provided parameter (no functional change).

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-06-12 20:08:18 +02:00
Oleksij Rempel 1f5c9638ab j1939acd: unify debug messages
Most of verbose messages are already stderr, make sure, rest of them do
the same.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2020-06-12 14:37:22 +02:00
Oleksij Rempel 1d3125bef2 j1939acd: do not exit on debug messages
Some debug messages were implemented using err(), which does not return,
but exit the program. This patches replaces the debug messages by
fprintf(stdout, ).

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2020-06-12 14:24:58 +02:00
Oliver Hartkopp 62f995601e Android.mk: Introduce LOCAL_VENDOR_MODULE to build in AOSP tree
Change path for canutils modules from system/bin to vendor/bin in the
case of building in AOSP tree.

https://github.com/linux-can/can-utils/pull/204

Suggested-by: Pavel Salomatov https://github.com/PsycheEYE
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-06-04 18:02:10 +02:00
Oliver Hartkopp 647210ee1c Android.mk: Add missing targets
The J1939 tools and asc2log was missing in the Android build.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-06-04 18:02:10 +02:00
josemicandOliver Hartkopp eac93ced80 can-j1939-kickstart.md: fix example in documentation 2020-05-30 19:32:32 +02:00
Gary BissonandOliver Hartkopp da42cf4bb5 Android.mk: fix Android 10 build
Android now uses clang with Werror by default which prevents from
building.
Removing Werror for the current warnings.

Signed-off-by: Gary Bisson <gary.bisson@boundarydevices.com>
2020-05-29 17:58:23 +02:00
Gary BissonandOliver Hartkopp 43610bd621 Fix arithmetic on a pointer warning
Signed-off-by: Gary Bisson <gary.bisson@boundarydevices.com>
2020-05-28 20:54:37 +02:00
Gary BissonandOliver Hartkopp 46895a41c5 Fix comparison type mismatch warnings
Signed-off-by: Gary Bisson <gary.bisson@boundarydevices.com>
2020-05-28 20:54:37 +02:00
Oliver Hartkopp 2c87dcf468 can-utils: fix unused variable warnings
As pointed out by Gary Bisson clang complains about unused variables in
some valid cases.

Reported-by: Gary Bisson <gary.bisson@boundarydevices.com>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-05-28 19:32:20 +02:00
Marc Kleine-BuddeandGitHub 8df3d1dd3f Merge pull request #205 from josemic/patch-2
Update j1939acd.c
2020-05-27 09:07:24 +02:00
josemicandGitHub 255e360233 Update j1939acd.c
Minor change, as jacd had been renamed to j1939acd.
2020-05-26 23:11:33 +02:00
Oliver Hartkopp d91288f754 README: cansniffer is now also 29 bit CAN ID capable
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-05-11 15:26:05 +02:00
Oliver Hartkopp 9b75c6020f asc2log: support milliseconds resolution in date/time string
While strptime() does not support fractions of seconds in the date/time
string some new asc files support the milliseconds resolution.

When detecting this new format the msecs are retrieved by a separate
sscanf() invocation and added to the timeval's tv_usec element.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-05-10 19:22:53 +02:00
Oliver HartkoppandGitHub 41c8ead6c0 Rework for CAN FD support and fixes for asc to log file conversion tools
Detailed change log:

log2asc:
- support CAN FD tags and Classic CAN frames
- support RTR frames including DLC values
- new option '-r' disable the RTR DLC value for potential compatibility reasons
- new option '-f' to use the CANFD format for Classic CAN too

asc2log:
- support CAN FD tags and Classic CAN frames
- be robust against fractions of seconds in date/time string
- fix reading of RTR frames including DLC values in Classic CAN parsing
- fix date/time string detection

cangen:
- new option '-E' to support ESI bit for CAN FD frame generation
(was needed for reference log file generation)
2020-05-10 16:45:21 +02:00
Oliver Hartkopp 3bb659d18d asc2log: fix handling for RTR frames in Classic CAN mode
Fix reading of the RTR representation without and with DLC (v8.5+ tools).

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-05-10 15:09:55 +02:00
Oliver Hartkopp 9cde2ebe8f asc2log: fix date string detection
The former check was too complex and did not catch all valid cases.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-05-10 14:41:34 +02:00
Oliver Hartkopp 7729c046c5 cangen: support ESI bit for CAN FD frame generation
The CAN FD frames support BTR and ESI as special flags. While BTR could
be generated by cangen the ESI bit could not be generated so far.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-05-10 12:03:35 +02:00
Oliver Hartkopp 61dbb56ef6 log2asc: support DLC values in Classic CAN RTR frames
RTR frames contain a valid DLC value which has not been exposed in the
ASC file format since v8.5 of the tools.

So log2asc will expose this DLC value by default which can be changed
by applying the '-r' option to create the former format.

It can be assumed that the tools pre v8.5 will ignore the value but
if not this switch will make sure to create the old format.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-05-10 11:45:03 +02:00
Oliver Hartkopp 3014d390b4 log2asc: support CANFD format also for Classic CAN
The CANFD tagged format also supports the encapsulation of Classic CAN
frames which is selected when logging on CAN FD capable CAN interfaces.

With a new option '-f' this CANFD format is selected.

Although this representation is even more inefficient it is seems to be
the common way and increases the readability for mixed CAN/CANFD logs.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-05-10 11:22:05 +02:00
Oliver Hartkopp ad9fc28f9e asc2log: add sanity checks for search pattern
Add some more sanity checks and increase readability for the sscanf()
procedure to read a CANFD tagged line.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-05-10 10:44:11 +02:00
Oliver Hartkopp 9a079942cd log2asc: support CANFD asc file generation
The CANFD asc format adds information about the CAN controllers bitrate
settings, CRCs and message length (in bits) and its duration.

The plan is to provide static values for these attributes that we can not
get from the log file anyway and stay on the 'old style' format for
classic CAN frames - which has been successfully tested on the latest tools.

The remaining drawback is that the 'old style' format is not able to
provide a DLC information for RTR frames.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-05-09 22:08:19 +02:00
Oliver Hartkopp ed9c646608 log2asc: reorder code to prepare CAN FD support
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-05-09 19:04:53 +02:00
Oliver Hartkopp df0b25c17e asc2log: support CANFD tagged asc file content
Handles CANFD asc files with classic CAN and CAN FD frames.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-05-09 18:42:55 +02:00
Oliver Hartkopp 3c8197e4d1 asc2log: make date time sting milliseconds aware
strptime() does not support milliseconds but the latest ASC logfile
also provides a fraction of seconds, e.g.

date Fri May 8 08:49:04.052 pm 2020

Read the value into the year variable before parsing the real year.
We will therefore omit the milliseconds resolution for now.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-05-09 18:19:24 +02:00
Oliver Hartkopp 43a3cca54d asc2log: reorder code to prepare CAN FD support
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-05-09 13:10:27 +02:00
Oliver Hartkopp becc0fc6cc cansniffer: fix buffer length in readsettings()
The Android build discovered a char buffer overflow in readsettings().

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-05-07 18:49:20 +02:00
Oliver HartkoppandGitHub c5cb7e1a7c Merge pull request #200 from hartkopp/29bit-cansniffer
cansniffer: support EFF frames with 29 bit CAN IDs

Convert cansniffer from CAN_BCM to CAN_RAW sockets and handle the
content filter in user space. Conversion CAN_RAW including slot
concept and sorting contributed by @coryjfowler.

Functional changes visible to users:
    
- New format for settings file (using 'r' and 'w' interactive commands)
- New command '8' to switch in a compact binary view for 80 columns view
- New head line layout
- The gap time between CAN frames is displayed in milli seconds (ms)
- The interactive filters support 29 bit CAN IDs
- New interactive command to clear/redraw the screen (<SPACE><ENTER>)
- New interactive commands to enable/disable SFF/EFF frames
    a<ENTER>        - enable 'a'll SFF CAN-IDs to sniff
    n<ENTER>        - enable 'n'one SFF CAN-IDs to sniff
    A<ENTER>        - enable 'A'll EFF CAN-IDs to sniff
    N<ENTER>        - enable 'N'one EFF CAN-IDs to sniff
- Fixes in bit change colorization and gap calculation detected at rework
2020-05-07 18:35:50 +02:00
Rasmus PedersenandGitHub 729e346d31 cangen.c: added -c option for bursty output. (#201)
added -c option for bursty output.
specify -c 100 to have 100 packets sent in burst before a gap.
use for example -p 1000 to avoid TX buffer full errors
2020-05-05 10:14:58 +02:00
Oliver Hartkopp 7575d43fd2 cangen: fix doubled description in help text
The help2man conversion created a second application description.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-04-29 19:11:41 +02:00
Oliver Hartkopp 2a8867f3cb cansniffer: add short description in help text
Following other can-utils applications.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-04-29 19:06:57 +02:00
Oliver Hartkopp ab2e8ffe0e cansniffer: formatting and variable renaming
Some unification of code formatting and rename of a variable in
print_snifline() which does not represent a CAN ID anymore.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-04-29 18:56:25 +02:00
Oliver Hartkopp ac55db508a cansniffer: exit after displaying help text
Do not start the application when the user wants to read the help text.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-04-29 09:55:28 +02:00
Oliver Hartkopp 64e33bf9ad cansniffer: add new interactive commands to enable/disable SFF/EFF frames
With the new commands

a<ENTER>        - enable 'a'll SFF CAN-IDs to sniff
n<ENTER>        - enable 'n'one SFF CAN-IDs to sniff
A<ENTER>        - enable 'A'll EFF CAN-IDs to sniff
N<ENTER>        - enable 'N'one EFF CAN-IDs to sniff

the EFF/SFF frames can be added/removed with a single command.
Of course this could be done with the '+' and '-' filters too.
But 'N' is much easier to type then '-0000000000000000' ...

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-04-29 09:52:20 +02:00
Oliver Hartkopp adf29573f4 cansniffer: add interactive command to clear/redraw the screen
For efficiency reasons on slow embedded machines cansniffer usually
does not clear the screen but only writes updates on required lines.
Sometimes the written lines exceed the terminal lines and people
resize the window which is not detected by cansniffer.

With entering <SPACE><ENTER> in interactive mode the screen can be
forced to redraw after resizing the terminal window.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-04-29 09:51:33 +02:00
Oliver Hartkopp bd6ef44321 cansniffer: support EFF frames with 29 bit CAN IDs
Convert cansniffer from CAN_BCM to CAN_RAW sockets and handle the
content filter in user space. Conversion CAN_RAW including slot
concept and sorting contributed by coryjfowler.

Functional changes visible to users:

- New format for settings file
- New command '8' to switch in a compact binary view for 80 columns view
- New head line layout
- The gap time between CAN frames is displayed in milli seconds (ms)
- The interactive filters support 29 bit CAN IDs

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-04-29 09:48:52 +02:00
Oliver Hartkopp 6d112a7209 cansniffer: terminate when settings file is not found
Clean up readsettings() and terminate when the settings file
'sniffset.*' is not found when given on commandline.

The readsettings() status output could not be read anyway due to
instant redraw from CAN frames.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-04-29 07:18:47 +02:00
Oliver Hartkopp 6f44582c19 cansniffer: make use of if_nametoindex()
Simplify the code as in other can-utils applications.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-04-29 06:57:16 +02:00
Oliver Hartkopp 507ff82d81 cansniffer: remove CAN_BCM specific functionalities
Remove functionalities that are not supported resp. can not be implemented
after the CAN_BCM to CAN_RAW conversion of cansnifffer.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-04-29 06:49:39 +02:00
Oliver Hartkopp 1665abf46f can-utils: fix missing include of libgen.h
The basename() function needs libgen.h to be included as otherwise this
will fail to compile in some environments.

Reported-by: Robert Schwebel <r.schwebel@pengutronix.de>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-04-28 19:14:52 +02:00
Oliver Hartkopp 853989bed2 canplayer: make help text fit into 80 colums again
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-04-28 19:01:45 +02:00
Oliver Hartkopp f3ced10007 cangw: make help text fit into 80 colums again
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-04-28 19:01:07 +02:00
Oliver Hartkopp 819a03f6e2 candump: fix/unify help text indention
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-04-28 18:59:37 +02:00
Oliver Hartkopp e266422c54 isotpdump: make help text fit into 80 colums again
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-04-28 18:57:26 +02:00
Oliver Hartkopp 5ca66d7bea slcanpty: simplify tool decription in help text
Simplify tool description and format the empty lines like in other
(e.g. slcand) tools.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-04-27 11:09:05 +02:00
Oliver Hartkopp d007263021 cansend: simplify tool decription in help text
Simplify tool description and format the empty lines like in other
(e.g. slcand) tools.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-04-27 10:53:02 +02:00
Oliver HartkoppandGitHub f91b537c01 Merge pull request #69 from gerasiov/help-reformat
Reformat output of help/usage information - Thanks Alexander!
2020-04-27 09:16:13 +02:00
Alexander GQ GerasiovandAlexander Gerasiov b43d1b4d27 cansend.c: Reformat help/usage output to be compatible with help2man.
Gbp-Pq: Name 0010-cansend.c-Reformat-help-usage-output-to-be-compatibl.patch
2020-04-27 08:20:09 +03:00
Alexander GQ GerasiovandAlexander Gerasiov f638cdc79b slcanpty.c: Reformat help/usage output to be compatible with help2man.
Gbp-Pq: Name 0029-slcanpty.c-Reformat-help-usage-output-to-be-compatib.patch
2020-04-27 08:20:09 +03:00
Alexander GQ GerasiovandAlexander Gerasiov d89b38de8a jcat.c: Reformat help/usage output to be compatible with help2man.
Gbp-Pq: Name 0028-jcat.c-Reformat-help-usage-output-to-be-compatible-w.patch
2020-04-27 08:20:09 +03:00
Alexander GerasiovandAlexander Gerasiov d39cb046d1 testj1939.c: Reformat help/usage output to be compatible with help2man.
Signed-off-by: Alexander Gerasiov <gq@debian.org>

Gbp-Pq: Name 0025-testj1939.c-Reformat-help-usage-output-to-be-compati.patch
2020-04-27 08:20:09 +03:00
Alexander GerasiovandAlexander Gerasiov 9e491bc553 slcand.c: Reformat help/usage output to be compatible with help2man.
Signed-off-by: Alexander Gerasiov <gq@debian.org>

Gbp-Pq: Name 0024-slcand.c-Reformat-help-usage-output-to-be-compatible.patch
2020-04-27 08:20:09 +03:00
Alexander GerasiovandAlexander Gerasiov 09f6dc6d17 slcan_attach.c: Reformat help/usage output to be compatible with help2man.
Signed-off-by: Alexander Gerasiov <gq@debian.org>

Gbp-Pq: Name 0023-slcan_attach.c-Reformat-help-usage-output-to-be-comp.patch
2020-04-27 08:20:09 +03:00
Alexander GerasiovandAlexander Gerasiov 8e6c11128d log2asc.c: Reformat help/usage output to be compatible with help2man.
Signed-off-by: Alexander Gerasiov <gq@debian.org>

Gbp-Pq: Name 0022-log2asc.c-Reformat-help-usage-output-to-be-compatibl.patch
2020-04-27 08:20:09 +03:00
Alexander GerasiovandAlexander Gerasiov 276688f2ad jsr.c: Reformat help/usage output to be compatible with help2man.
Signed-off-by: Alexander Gerasiov <gq@debian.org>

Gbp-Pq: Name 0021-jsr.c-Reformat-help-usage-output-to-be-compatible-wi.patch
2020-04-27 08:20:09 +03:00
Alexander GerasiovandAlexander Gerasiov 0155472ee0 jspy.c: Reformat help/usage output to be compatible with help2man.
Signed-off-by: Alexander Gerasiov <gq@debian.org>

Gbp-Pq: Name 0020-jspy.c-Reformat-help-usage-output-to-be-compatible-w.patch
2020-04-27 08:20:09 +03:00
Alexander GQ GerasiovandAlexander Gerasiov 211c5cea49 can-calc-bit-timing.c: Reformat help/usage output to be compatible with help2man.
Gbp-Pq: Name 0020-can-calc-bit-timing.c-Reformat-help-usage-output-to-.patch
2020-04-27 08:20:09 +03:00
Alexander GQ GerasiovandAlexander Gerasiov c1fdfb09fc jcat.c: Reformat help/usage output to be compatible with help2man.
Signed-off-by: Alexander GQ Gerasiov <gq@cs.msu.su>

Gbp-Pq: Name 0019-jcat.c-Reformat-help-usage-output-to-be-compatible-w.patch
2020-04-27 08:20:09 +03:00
Alexander GerasiovandAlexander Gerasiov 506252e9bc jacd.c: Reformat help/usage output to be compatible with help2man.
Signed-off-by: Alexander Gerasiov <gq@debian.org>

Gbp-Pq: Name 0019-jacd.c-Reformat-help-usage-output-to-be-compatible-w.patch
2020-04-27 08:20:09 +03:00
Alexander GerasiovandAlexander Gerasiov 89c66aba5f isotptun.c: Reformat help/usage output to be compatible with help2man.
Signed-off-by: Alexander Gerasiov <gq@debian.org>

Gbp-Pq: Name 0018-isotptun.c-Reformat-help-usage-output-to-be-compatib.patch
2020-04-27 08:20:09 +03:00
Alexander GQ GerasiovandAlexander Gerasiov c61c9bc030 isotpsniffer.c: Reformat help/usage output to be compatible with help2man.
Gbp-Pq: Name 0017-isotpsniffer.c-Reformat-help-usage-output-to-be-comp.patch
2020-04-27 08:20:09 +03:00
Alexander GQ GerasiovandAlexander Gerasiov 9240ccfcb7 isotpserver.c: Reformat help/usage output to be compatible with help2man.
Gbp-Pq: Name 0016-isotpserver.c-Reformat-help-usage-output-to-be-compa.patch
2020-04-27 08:20:09 +03:00
Alexander GerasiovandAlexander Gerasiov 3d6a53550e isotpsend.c: Reformat help/usage output to be compatible with help2man.
Signed-off-by: Alexander Gerasiov <gq@debian.org>

Gbp-Pq: Name 0015-isotpsend.c-Reformat-help-usage-output-to-be-compati.patch
2020-04-27 08:20:09 +03:00
Alexander GQ GerasiovandAlexander Gerasiov 1cf4d86874 isotprecv.c: Reformat help/usage output to be compatible with help2man.
Gbp-Pq: Name 0014-isotprecv.c-Reformat-help-usage-output-to-be-compati.patch
2020-04-27 08:20:09 +03:00
Alexander GerasiovandAlexander Gerasiov 4db63e4b55 isotpperf.c: Reformat help/usage output to be compatible with help2man.
Signed-off-by: Alexander Gerasiov <gq@debian.org>

Gbp-Pq: Name 0013-isotpperf.c-Reformat-help-usage-output-to-be-compati.patch
2020-04-27 08:20:09 +03:00
Alexander GQ GerasiovandAlexander Gerasiov 24af048812 isotpdump.c: Reformat help/usage output to be compatible with help2man.
Gbp-Pq: Name 0012-isotpdump.c-Reformat-help-usage-output-to-be-compati.patch
2020-04-27 08:20:09 +03:00
Alexander GerasiovandAlexander Gerasiov 4568d4a180 cansniffer.c: Reformat help/usage output to be compatible with help2man.
Signed-off-by: Alexander Gerasiov <gq@debian.org>

Gbp-Pq: Name 0011-cansniffer.c-Reformat-help-usage-output-to-be-compat.patch
2020-04-27 08:20:09 +03:00
Alexander GerasiovandAlexander Gerasiov 3e2c1d3cbd canplayer.c: Reformat help/usage output to be compatible with help2man.
Signed-off-by: Alexander Gerasiov <gq@debian.org>

Gbp-Pq: Name 0009-canplayer.c-Reformat-help-usage-output-to-be-compati.patch
2020-04-27 08:20:08 +03:00
Alexander GerasiovandAlexander Gerasiov 65399166c1 canlogserver.c: Reformat help/usage output to be compatible with help2man.
Signed-off-by: Alexander Gerasiov <gq@debian.org>

Gbp-Pq: Name 0008-canlogserver.c-Reformat-help-usage-output-to-be-comp.patch
2020-04-27 08:20:08 +03:00
Alexander GQ GerasiovandAlexander Gerasiov 1127609357 cangw.c: Reformat help/usage output to be compatible with help2man.
Gbp-Pq: Name 0007-cangw.c-Reformat-help-usage-output-to-be-compatible-.patch
2020-04-27 08:20:08 +03:00
Alexander GerasiovandAlexander Gerasiov f503097a38 cangen.c: Reformat help/usage output to be compatible with help2man.
Signed-off-by: Alexander Gerasiov <gq@debian.org>

Gbp-Pq: Name 0006-cangen.c-Reformat-help-usage-output-to-be-compatible.patch
2020-04-27 08:20:08 +03:00
Alexander GerasiovandAlexander Gerasiov c56259ab33 canfdtest.c: Reformat help/usage output to be compatible with help2man.
Signed-off-by: Alexander Gerasiov <gq@debian.org>

Gbp-Pq: Name 0005-canfdtest.c-Reformat-help-usage-output-to-be-compati.patch
2020-04-27 08:20:08 +03:00
Alexander GQ GerasiovandAlexander Gerasiov 6db632531d candump.c: Reformat help/usage output to be compatible with help2man.
Gbp-Pq: Name 0004-candump.c-Reformat-help-usage-output-to-be-compatibl.patch
2020-04-27 08:20:08 +03:00
Alexander GerasiovandAlexander Gerasiov f4a9e5b57d can-calc-bit-timing.c: Reformat help/usage output to be compatible with help2man.
Signed-off-by: Alexander Gerasiov <gq@debian.org>

Gbp-Pq: Name 0003-can-calc-bit-timing.c-Reformat-help-usage-output-to-.patch
2020-04-27 08:20:08 +03:00
Alexander GerasiovandAlexander Gerasiov 69865c8247 canbusload.c: Reformat help/usage output to be compatible with help2man.
Signed-off-by: Alexander Gerasiov <gq@debian.org>

Gbp-Pq: Name 0002-canbusload.c-Reformat-help-usage-output-to-be-compat.patch
2020-04-27 08:20:08 +03:00
Alexander GerasiovandAlexander Gerasiov b740fb7fab asc2log.c: Reformat help/usage output to be compatible with help2man.
Signed-off-by: Alexander Gerasiov <gq@debian.org>

Gbp-Pq: Name 0001-asc2log.c-Reformat-help-usage-output-to-be-compatibl.patch
2020-04-27 08:20:08 +03:00
Oliver Hartkopp bceadb8696 cansniffer: fix colorization when notching relevant bits
When notching marked (and colored) bits with the interactive '#' command
the binary output omits colored bits - as intended.

But when switching back to the hex and ASCII output the bytes with
notched bits remained uncolored even when some bits inside the hex bytes
would have needed to be colored.

The check for the colored output was a logical AND operation which is
fine for the binary representation but needed to be a bit-wise operation
in the hex/ASCII byte mode case.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-04-26 15:56:08 +02:00
Oliver Hartkopp eb639c1b3d cansniffer: fix gap calculation output
The gap between two consecutive frames of a specific has been calculated in
handle_timeo() instead of handle_bcm() which lead to values that where
at minimum the loop time of the display refresh.

The effect can be seen when displaying a 10ms gap CAN frame with a 200ms
display refresh (option -l 20 => default) in opposite to a 10ms display
refresh (option -l 1).

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-04-26 08:30:55 +02:00
Marc Kleine-BuddeandGitHub 6cdccbbafc Merge pull request #199 from gerasiov/j1939rename
Rename j* to j1939\1
2020-04-24 13:01:51 +02:00
Alexander GQ Gerasiov 8106214b55 Rename j* to j1939\1
Using j*smthng* for j1939-related tools is not very good for 2 reasons:
1. j prefix is not very informative;
2. jcat name is used by journal cat tool from popular sleuthkit toolkit;
2`. jacd sounds very similar to jackd.
2``. Possible future name conflicts for new tools.

Thus I renamed j* to j1939\1 to deal with this issue.

Signed-off-by: Alexander GQ Gerasiov <gq@cs.msu.su>
2020-04-20 10:18:13 +03:00
Oliver Hartkopp da65fdfe0d isotpsniffer: only invoke LL_OPTS setsockopt when set on commandline
In commit da33f96edf ("isotpsniffer: Add support for llopts") the
setsockopt() syscall for the link layer options CAN_ISOTP_LL_OPTS
has been added.

Unfortunately the syscall has been invoked even if there were no values
given on the command line and 'zero values' have been passed to the
kernel which correctly answered with -EINVAL.

And a missing check for a mandatory non-zero value for the MTU.

Fixes: da33f96edf ("isotpsniffer: Add support for llopts")
Reported by: https://github.com/ikuyas
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-02-04 17:28:11 +01:00
Oliver Hartkopp ae69062657 isotpsniffer: remove duplicated code
In commit da33f96edf ("isotpsniffer: Add support for llopts") the setsockopt
call has been executed twice. (copy & paste issue?)

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-02-04 08:31:48 +01:00
Marc Kleine-Budde 506f6f3043 canfdtest: can_echo_gen(): initialize tx_frames with zero
This avoids having the padding in the struct can_fame contain bogus
values, which are interpreted by "candump -x" as CAN-FD BRS and ESI
values.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2020-02-03 23:58:34 +01:00
Oliver HartkoppandGitHub 8027b498cf Merge pull request #191 from hartkopp/candump-remove-bridging
candump: remove bridging functionality
2020-02-01 09:55:23 +01:00
Oliver Hartkopp a9985c7652 candump: remove bridging functionality
The tool 'candump' is used to dump CAN traffic to stdout or logfile.
In early days where the in-kernel CAN gateway (can-gw) with the cangw tool was
not yet implemented the bridging functionality allowed to send received (and
filtered) CAN frames to another outgoing CAN interface.

As we now have can-gw and sending CAN frames from a 'reading tool' seems wrong
especially from the Unix philosophy "Write programs that do one thing and do
it well." this patch removes the obsolete functionality from candump.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2020-01-04 14:11:34 +01:00
Marc Kleine-BuddeandGitHub 665d8699eb Merge pull request #172 from jluebbe/jluebbe-actions
add github actions
2019-12-06 13:55:33 +01:00
Marc Kleine-BuddeandGitHub 4e36059f6a Merge pull request #175 from olerem/testj1938
sync testj1939 with latest kernel UAPI
2019-12-06 11:41:10 +01:00
Marc Kleine-BuddeandGitHub 6831eeeb62 Merge pull request #180 from olerem/jacd
jacd: remove SO_BINDTODEVICE setsockopt call
2019-12-06 11:31:53 +01:00
Oleksij Rempel a8456276df jacd: remove SO_BINDTODEVICE setsockopt call
This was used in the non mainline stack version.
Removing this call allows to use jacd without root permissions.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2019-12-06 11:24:44 +01:00
Marc Kleine-BuddeandGitHub 6eeedb0e66 Merge pull request #177 from marckleinebudde/fix-error-handling
isotpsniffer: fix error handling, "0" is a valid filedescriptor
2019-12-02 19:16:55 +01:00
Marc Kleine-Budde b6a44803fd isotpsniffer: fix error handling, "0" is a valid filedescriptor
Fixes: b04108c615 ("isotpsniffer: Fix error handling")
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2019-12-02 11:20:03 +01:00
Oleksij Rempel 153501c0ab can-j1939-kickstart: remove "Use source address" example
This example do not really demonstrate UAPI or testj1939 functionality.
So, remove it.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2019-12-02 08:29:45 +01:00
Oleksij Rempel 8cf6353039 can-j1939-kickstart: update documentation for testj1939
testj1939 need to use -B (broadcast) flag to be able to send or receive
broadcast packages.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2019-11-29 14:16:04 +01:00
Oleksij Rempel 5d3f8073b2 testj1939: add optional promiscuous mode and boradcast support
Upstream version of J1939 stack has different UAPI. To make documented
testj1939 examples work again we need at least boradcast flag.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2019-11-29 13:53:55 +01:00
Jan Luebbe d75122f649 add github actions 2019-11-25 15:29:47 +01:00
Oliver HartkoppandGitHub 9ae877ce32 Merge pull request #169 from rumpelsepp/isotpsniffer
isotpsniffer: add llopts support, use isprint() instead of open coded check and clean up error paths.
2019-11-14 13:54:05 +01:00
Stefan Tatschner da33f96edf isotpsniffer: Add support for llopts 2019-11-14 13:10:49 +01:00
Stefan Tatschner b04108c615 isotpsniffer: Fix error handling 2019-11-14 13:00:21 +01:00
Stefan Tatschner ecf80e8f91 isotpsniffer: Use isprint() instead of manual check 2019-11-14 07:23:28 +01:00
Yegor YefremovandGitHub bf30a4bc01 Merge pull request #167 from yegorich/err-handling
libj1939: fix missing include and syntax
2019-11-12 10:05:48 +01:00
Yegor Yefremov 63d9a3d87b libj1939: fix missing include and syntax
Include err.h and remove the unneeded parameter errno and
its header include.

Fixes: 791b6de ("treewide: Fix compilation on libmusl, replace error() by err()")

Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
2019-11-12 10:04:24 +01:00
Yegor YefremovandGitHub c0dba0a454 Merge pull request #166 from yegorich/sync-headers
include: import header files from kernel v5.4-rc7
2019-11-12 10:02:20 +01:00
Yegor YefremovandGitHub a67bf7aa89 Merge pull request #168 from yegorich/typo
jacd: fix typo in a comment
2019-11-12 10:01:57 +01:00
Yegor Yefremov 276077de00 jacd: fix typo in a comment
s/ourselve/ourselves

Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
2019-11-12 09:06:17 +01:00
Yegor Yefremov ffd60c9b74 include: import header files from kernel v5.4-rc7
Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
2019-11-12 08:59:58 +01:00
Yegor YefremovandGitHub 8426d63ecf Merge pull request #165 from yegorich/spelling
Fix spelling in various files
2019-11-11 14:40:26 +01:00
Yegor Yefremov 14ccc06eba Fix spelling in various files
codespell parameters:

codespell -q 3 --skip="*.in,*.sh,*.m4,config,configure,autom4te.cache"

Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
2019-11-11 14:21:49 +01:00
Marc Kleine-BuddeandGitHub 35b2ef691c Merge pull request #163 from marckleinebudde/libmusl-fix
treewide: Fix compilation on libmusl, replace error() by err()
2019-10-31 08:57:29 +01:00
Marc Kleine-BuddeandGitHub a08b61621d Merge pull request #162 from josemic/patch-1
Update can-j1939-kickstart.md
2019-10-31 08:52:13 +01:00
josemicandGitHub 275f606a1f Update can-j1939-kickstart.md
Added the padding to the candump output.
2019-10-30 19:22:23 +01:00
Marc Kleine-Budde 791b6de786 treewide: Fix compilation on libmusl, replace error() by err()
Reported-by: Brandon Ros <brandonros1@gmail.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2019-10-30 11:59:49 +01:00
Oliver HartkoppandGitHub 7e9bc7719b Merge pull request #155 from yegorich/reuse-fixes
Reuse fixes
2019-09-26 20:14:40 +02:00
Yegor Yefremov 0b93e9836f libj1939.h: add missing license and copyright header
Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
2019-09-26 15:46:20 +02:00
Yegor Yefremov d66295ee75 Add license texts as files
Add license texts mentioned by REUSE tool.

Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
2019-09-26 15:45:43 +02:00
Oliver HartkoppandGitHub 26ae1fffa8 Merge pull request #154 from yegorich/readme-fix
README: update the list of CAN over IP tools
2019-09-19 19:17:15 +02:00
Yegor Yefremov de8bb5fd8f README: update the list of CAN over IP tools
Fix socketcand URL and add cannelloni.

Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
2019-09-19 14:14:36 +02:00
Marc Kleine-BuddeandGitHub a8d4827d0f Merge pull request #151 from olerem/recvown 2019-08-26 14:16:05 +02:00
Oleksij Rempel 7337cb12de j1939: drop SO_J1939_RECV_OWN support
SO_J1939_RECV_OWN is no longer supported by the kernel. So, sync the
headers and rework jacd.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2019-08-26 11:03:36 +02:00
Oleksij Rempel d5ba0e2d23 can/j1939.h: sync with latest kernel state
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2019-08-26 11:03:36 +02:00
Oliver Hartkopp 226d6393b8 slcan tools: fix stringop-truncation warnings
Rework string handling for ioctl() syscalls for netdev name operations.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2019-08-25 18:25:35 +02:00
Oliver Hartkopp 1331c56393 isotptun: fix stringop-truncation warnings
Rework string handling for ioctl() syscalls for netdev name operations.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2019-08-25 18:20:37 +02:00
Oliver Hartkopp 319bd5de45 candump: silence format-overflow warning
When -Wformat-overflow= is enabled the gcc notes ...
"‘sprintf’ output between 30 and 82 bytes into a destination of size xx"
Increasing the buffer for the file name to 83 bytes removes the warning.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2019-08-23 19:57:06 +02:00
Oliver Hartkopp 83a1210b75 candump: preserve silent mode with enabled log file output format
As seen in https://github.com/linux-can/can-utils/issues/150 the logfile
format switch ignores the silent mode switch.

Fix this by checking the silent mode when using logfile format on stdout.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2019-08-23 19:40:27 +02:00
Oliver Hartkopp 818dacd78f candump: fix formatting of status messages regarding standard output
As remarked by Victor in https://github.com/linux-can/can-utils/issues/150
the output in the case of silent mode has puzzled line feeds.

Reported-by: Victor Cushman <VictorSCushman@gmail.com>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2019-08-23 19:34:10 +02:00
Oliver Hartkopp d45f3f46bd cangw: add CAN FD support
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2019-08-16 15:32:16 +02:00
Oliver Hartkopp 07054c06f5 cangw: remove sanity checks that are better handled in the kernel
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2019-08-16 15:26:58 +02:00
Oliver Hartkopp 24923df749 cangw: add new command line option '-X' to handle CAN FD rules
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2019-08-16 15:26:50 +02:00
Oliver Hartkopp 0669215a4b cangw: update include files for CAN FD support
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2019-08-16 15:26:41 +02:00
jogo-andOliver Hartkopp 9aa993df4c isotpdump: fix service 0x23 naming according to UDS specification
Fix Service 0x23 naming according to the standard
"ReadDataByMemory" -> "ReadMemoryByAddress"

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2019-07-30 22:09:50 +02:00
Marc Kleine-BuddeandGitHub c10c049ce7 Merge pull request #147 from ffontaine/master
fix include to find SIOCGSTAMP with latest kernel
2019-07-15 08:34:00 +02:00
Fabrice Fontaine e9590b1ca7 fix include to find SIOCGSTAMP with latest kernel
In linux kernel commit 0768e17073dc527ccd18ed5f96ce85f9985e9115
the asm-generic/sockios.h header no longer defines SIOCGSTAMP.
Instead it provides only SIOCGSTAMP_OLD.

The linux/sockios.h header now defines SIOCGSTAMP using either
SIOCGSTAMP_OLD or SIOCGSTAMP_NEW as appropriate. This linux only
header file is not pulled so we get a build failure.

canlogserver.c: In function 'main':
canlogserver.c:404:21: error: 'SIOCGSTAMP' undeclared (first use in this function); did you mean 'SIOCGRARP'?
     if (ioctl(s[i], SIOCGSTAMP, &tv) < 0)
                     ^~~~~~~~~~
                     SIOCGRARP
canlogserver.c:404:21: note: each undeclared identifier is reported only once for each function it appears in

Fixes:
 - http://autobuild.buildroot.org/results/363de7d9bf433be8bc47ba4ee52ae0bb80fa9021

Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
2019-07-14 22:14:10 +02:00
Yegor YefremovandGitHub 9ffb16495c Merge pull request #146 from yegorich/gpl-2-only
Relicense GPL-2.0-or-later files to GPL-2.0-only
2019-07-10 22:47:11 +02:00
Yegor Yefremov 59f92965b9 Relicense GPL-2.0-or-later files to GPL-2.0-only
This way all licenses in the project will be homogenised.

Acked-by: Marc Kleine-Budde <mkl@pengutronix.de>
Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>
Acked-by: Sven Schmitt <sven.schmitt@gmx.net>
Acked-by: Oleksij Rempel <ore@pengutronix.de>
Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Acked-by: Brennan Ashton <bashton@brennanashton.com>
Acked-By: IOhannes m zmölnig <zmoelnig@iem.at>
Acked-by: Frank Theile <ftheile@grundfos.com>
Acked-by: Wolfgang Grandegger <wg@grandegger.com>
Acked-by: Jeremiah Mahler <jmmahler@gmail.com>
Acked-by: Jonathan Challinger <mr.challinger@gmail.com>
Acked-by: Cheng-Lung Lee <chenglung@gmail.com>
Acked-by: Ramesh Shanmugasundaram <rashanmu@gmail.com>
Acked-by: Mans Rullgard <mans@mansr.com>
Acked-by: Søren Holm <sgh@sgh.dk>
Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
2019-07-10 14:01:23 +02:00
Yegor YefremovandGitHub 9d0c08d8cb Merge pull request #143 from yegorich/spdx
Add SPDX identifiers
2019-07-10 13:42:21 +02:00
Marc Kleine-BuddeandGitHub bb2cc1140f Merge pull request #144 from olerem/errq-2019.05.25
queue status
2019-06-27 12:05:52 +02:00
Oleksij Rempel c4e68aff78 jcat: get status for all queued messages
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2019-06-25 07:36:36 +02:00
Oleksij Rempel 0e542c8dba jcat: make sure we can use decimal numbers for repeat parameter
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2019-06-24 13:53:31 +02:00
Yegor Yefremov 7b7331976a Add SPDX identifiers
Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
2019-06-19 12:24:24 +02:00
Marc Kleine-BuddeandGitHub a965086356 Merge pull request #140 from marckleinebudde/isotpdump
isotpdump: fix compiler warning
2019-06-03 20:26:11 +02:00
Marc Kleine-Budde 8ada533538 isotpdump: fix compiler warning
| isotpdump.c: In function ‘print_uds_message’:
| isotpdump.c:94:29: warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
|   } else if (service >= 0x10 && service <= 0x3E ||
|              ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
| isotpdump.c:96:22: warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
|       service >= 0xBA && service <= 0xBE)
|       ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2019-06-03 19:56:27 +02:00
Oliver HartkoppandGitHub f185160bfb Merge pull request #139 from buecheko/uds-dump
Add UDS output functionality to isotpdump
2019-05-30 20:37:42 +02:00
tr1core 0d8b0a8837 Add uds output functionality 2019-05-29 10:49:42 +02:00
Marc Kleine-BuddeandGitHub 045f75ad64 Merge pull request #135 from olerem/errq-2019.05.09.1
Provide error queue support
2019-05-09 14:50:29 +02:00
Oleksij RempelandMarc Kleine-Budde 25025d05ae jcat: add repeat support
Add option to resend same data without closing the socket.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2019-05-09 14:40:16 +02:00
Oleksij RempelandMarc Kleine-Budde edcce70373 jcat: provide errqueue support
The J1939 errqueue is a feedback interface to notify userspace
applications about actual transfer status. For now we can get
information about amount of data already send to the peer and errors
if session was aborted.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2019-05-09 14:40:16 +02:00
Oleksij RempelandMarc Kleine-Budde 05368ef1ae jcat: rework poller
Make poller to be a main part of the send loop. It should make
application more understandable.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2019-05-09 14:40:16 +02:00
Oleksij RempelandMarc Kleine-Budde 05a66d63fa jcat: enable polling by default
and set more or less meaningful default value.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2019-05-09 14:40:16 +02:00
Marc Kleine-Budde 6260263ef3 buildsystem: add SCM_TIMESTAMPING_OPT_STATS if not already defined 2019-05-09 14:40:16 +02:00
Oleksij RempelandMarc Kleine-Budde 9ff370ea82 include: add errqueue.h, net_tstamp.h, netlink.h
this headers are take from kernel v5.0 and needed for
error queue support.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2019-05-09 14:36:53 +02:00
Marc Kleine-BuddeandGitHub e92806db21 Merge pull request #136 from olerem/namefix
libj1939: fix name parsing
2019-05-09 12:29:58 +02:00
Oleksij Rempel 5e342e3c50 libj1939: fix name parsing
name is 8 byte long.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2019-05-09 12:09:11 +02:00
Oleksij Rempel 38fa644069 include: import header files from linux-5.0 (including new j1939 filter struct)
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2019-05-08 10:53:00 +02:00
Marc Kleine-BuddeandGitHub afb88e9019 Merge pull request #134 from marckleinebudde/uapi
j1939: port j1939 tools to new UAPI
2019-04-04 11:00:53 +02:00
Oleksij RempelandMarc Kleine-Budde 19d41bec45 jcat: allow to re-send rest of the buffer if we was interrupted
latest version of UAPI allows to continue sending on some signals.

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
2019-04-04 10:53:17 +02:00
Oleksij RempelandMarc Kleine-Budde 48a4a4bef4 jcat: user recv() instead of recvfrom()
No information from recvfrom() is currently used. So, it is enough to
use plain recv().

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2019-04-04 10:45:33 +02:00
Oleksij RempelandMarc Kleine-Budde b931fb514c jcat: add missing close of outfile and j1939 socket
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2019-04-04 10:45:33 +02:00
Oleksij RempelandMarc Kleine-Budde 7192b0b9d7 jacd: set SO_BROADCAST
with latest UAPI version we should set this flag to be allowed to send
broadcast frames with broadcast destination address. Even if on CAN
every thing is a broadcast...

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2019-04-04 10:37:52 +02:00
Oleksij RempelandMarc Kleine-Budde b8a2fa319a jacd: use sendto instead of send
Accordint to the new UAPI version, bind() with PGN set, should not be used
for destination PGN.

This change should work with new and old version of UAPI.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2019-04-04 10:37:49 +02:00
Oleksij RempelandMarc Kleine-Budde 314f8a92ae j1939: use defines instead of magic values
for now cover most of PGN values.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2019-04-04 10:37:39 +02:00
Marc Kleine-Budde 06d3beb08c include: import header files from linux-5.0 (including new j1939 patches)
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2019-04-04 10:19:11 +02:00
Marc Kleine-BuddeandGitHub 83667e822c Merge pull request #130 from marckleinebudde/testj1939
testj1939: use %zu to as format string to print sizeof()
2019-03-12 12:52:13 +01:00
Marc Kleine-Budde 9f60ed6fa0 testj1939: use %zu to as format string to print sizeof()
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2019-03-12 12:37:27 +01:00
Marc Kleine-BuddeandGitHub e1d5ee9907 Merge pull request #129 from marckleinebudde/cleanup
This pull request cleans up the Makefile by sorting things alphabetically and adding a missing newline to the GNUmakefile.am.
2019-03-12 12:34:42 +01:00
Marc Kleine-Budde c59dff1bb1 NUmakefile.am: EXTRA_DIST: add missing \
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2019-03-12 12:02:44 +01:00
Marc Kleine-Budde 4a1818aa55 Makefile: cleanup
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2019-03-12 10:14:27 +01:00
Oliver Hartkopp b6cb9a04e5 cansend: enhance help text to point out SFF/EFF identifiers
As suggested by https://github.com/jogo- an example was added that points
out how to send a CAN frame with CAN ID 123 as SFF (11 bit) and EFF (29 bit).

Reference: https://github.com/linux-can/can-utils/issues/126

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2019-02-14 09:47:46 +01:00
Oliver Hartkopp 46d620b27c cansend: enhance help text for length info in RTR frames
In 'classic' CAN 2.0 the RTR frames contain a length information in the
can_dlc field of a CAN frame control section. This length can be passed
to 'cansend' which has not been documented in the help text so far.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2019-02-13 14:55:47 +01:00
Marc Kleine-BuddeandGitHub 2328c6cfa0 Merge pull request #119 from twasilczyk/master
Don't build libj1939 for Android
2019-01-14 14:48:48 +01:00
Marc Kleine-BuddeandGitHub e0277cc960 Merge pull request #122 from olerem/test
testj1939: split output string in to 8 byte strings
2019-01-14 10:03:42 +01:00
Marc Kleine-BuddeandGitHub 7b70a433cf Merge pull request #121 from olerem/size
testj1939: fail if we use unsupported size
2019-01-14 10:03:34 +01:00
Oleksij Rempel 5551de5e56 testj1939: split output string in to 8 byte strings
Currently if we send lots of bytes, test1939 output will get unreadable.
Make it easier to read by splitting output dump.
New format will looks as following example:
root@DistroKit:~ testj1939 can0:0x90 -r
80 12300: 01 23 45 67 89 ab cd ef
00008     01 23 45 67 89 ab cd ef
00010     01 23 45 67 89 ab cd ef
00018     01 23 45 67 89 ab cd ef
00020     01 23 45 67 89 ab cd ef
00028     01 23 45 67 89 ab cd ef
00030     01 23 45 67 89 ab cd ef
00038     01 23 45 67 89 ab cd ef
00040     01 23 45 67 89 ab cd ef
00048     01 23 45 67 89 ab cd ef
00050     01 23 45 67 89 ab cd ef
00058     01 23 45 67 89 ab cd ef
00060     01 23 45 67 89 ab cd ef
00068     01 23 45 67 89 ab cd ef
00070     01 23 45 67 89 ab cd ef
00078     01 23 45 67 89 ab cd ef

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2019-01-14 09:19:51 +01:00
Oleksij Rempel ed5b495da6 testj1939: fail if we use unsupported size
Currently if we set size which is more then 128 byte
will silently ignore provided value and send only maximal
supported size.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2019-01-14 09:16:05 +01:00
Tomasz Wasilczyk 4da344b2aa Don't build j1939 for Android
This library uses if_nameindex symbol, not available at this system.
2019-01-10 12:03:06 -08:00
Oliver HartkoppandGitHub 8991b5c47d Merge pull request #118 from twasilczyk/master
Silence false positive unaligned pointer access warning
2019-01-10 19:28:12 +01:00
Tomasz Wasilczyk f6e07960d3 Silence false positive unaligned pointer access warning
This is a warning coming up on Android (ARM) platform.
Clang 4.x creates a false positive here: the can_id is the first
(and aligned) value in the packed struct modattr, so it's always
aligned if the struct itself is aligned.
2019-01-10 10:04:37 -08:00
Marc Kleine-BuddeandGitHub 02b87eb120 Merge pull request #117 from olerem/jcat-fixup
jcat: inverse if logic
2019-01-04 14:43:25 +01:00
Oleksij Rempel 5b68a2cef1 jcat: inverse if logic
it was if(offset != NULL), so it should be if(offset)

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2019-01-04 14:40:07 +01:00
Marc Kleine-BuddeandGitHub 0083a3762b Merge pull request #114 from olerem/jcat-2018.12.14
add jcat
2019-01-04 13:56:12 +01:00
Oleksij Rempel 23e5e227ac add jcat
jcat is kind of netcat for j1939
for example:
jcat can0:0x90 -r > /tmp/some_file

jcat -i some_file_to_send can0:0x80 :0x90,0x12300

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2019-01-04 13:01:11 +01:00
Oleksij Rempel e649b6ee2a libj1939: add libj1939_parse_canaddr and reuse it by testj1939
this function will be needed jcat

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2019-01-04 13:00:33 +01:00
Oliver Hartkopp c45a17e96b candump: try to switch bridge socket into CAN FD mode
When using the -b/-B option to send received CAN frames to the brigde interface
the sending failed when processing CAN FD frames. This patch enables CAN FD on
the socket for the bridging interface.

https://github.com/linux-can/can-utils/issues/104

Reported-by: https://github.com/jm3lee
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2018-10-24 09:36:55 +02:00
Oliver Hartkopp 8681e57230 candump: fix EFF CAN ID representation in CAN filter parameter
The documentation stated that the CAN ID is assumed to be an extended CAN
identifier (29 bit ID / EFF) when "can_id and can_mask are both 8 digits".
The check for the CAN ID length to be 8 is common in other CAN utils
(e.g. cansend) but it has never been implemented in candump.

This patch adds that check for EFF CAN IDs and clarifies the documentation.

Thanks to Nick for pointing out this inconsistency!

Reported-by: Nick Elmschig <nick@ikerobotics.com>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2018-10-23 21:22:11 +02:00
Marc Kleine-BuddeandGitHub 3f2bc6e1ea Merge pull request #108 from nick-ike/candump-usage-typo
Fix CAN ID typo in candump usage, to 12345678
2018-10-09 00:02:58 +02:00
Nick Elmschig 371d8e6da4 Fix CAN ID in candump usage, should be 12345678 2018-10-08 13:26:15 -07:00
Marc Kleine-BuddeandGitHub 12664efa9f Merge pull request #105 from marckleinebudde/cmake-cleanup
Cmake cleanup
2018-10-05 00:08:24 +02:00
Marc Kleine-Budde 04c171c285 CMakeLists.txt: build proper static libraries
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2018-10-04 23:55:54 +02:00
Marc Kleine-Budde 572a66fb94 CMakeLists.txt: clean up a bit
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2018-10-04 23:55:54 +02:00
Marc Kleine-Budde a6954bdaae CMakeLists.txt: Add missing N_SLCAN define 2018-10-04 23:55:54 +02:00
Marc Kleine-BuddeandGitHub 1c81f7fb2d Merge pull request #100 from yegorich/fix-return-value-checks
Add missing return value checks
2018-09-27 12:57:16 +02:00
Marc Kleine-BuddeandGitHub 5b8145f63d Merge pull request #99 from olerem/canfdtest-2018.09.18
Extend canfdtest to test proper RX and TX-ECHO order
2018-09-21 12:04:05 +02:00
Marc Kleine-BuddeandGitHub 3e4d589fec Merge pull request #101 from olerem/testj1938
add bind related options to testj1939
2018-09-21 11:44:49 +02:00
Bastian StenderandOleksij Rempel 54ff81cc40 testj1939: add omit bind option
This option is needed for j1939 socket functionality test.
Connects wihout bind should not work.

Signed-off-by: Bastian Stender <bst@pengutronix.de>
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2018-09-21 11:31:22 +02:00
Bastian StenderandOleksij Rempel 1ba9b86451 testj1939: add re-bind support
This option is needed for j1939 socket functionality test.
Binding to a socket and rebinding to the socket with e.g. a different SA
should work.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Signed-off-by: Bastian Stender <bst@pengutronix.de>
2018-09-21 11:31:04 +02:00
Yegor Yefremov 1ce4dc7b39 Add missing return value checks
Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
2018-09-18 13:43:29 +02:00
Oleksij RempelandOleksij Rempel ba603c59ae canfdtest: test if TX and RX msg are properly ordered
In some cases we can get local TX echo after remote response
for same TXed message was already received.

For applications which relay on proper order of TXed and RXed
message this will be fatal.

With this patch the package generating side will test if TX and RX are
properly ordered.
Currently with following commands, this issue can be easily
reproducible:
canfdtest -g can0 &
while(true); do chrt 40 dd if=/dev/zero of=/dev/null count=10000; done

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
2018-09-18 11:57:33 +02:00
Oleksij RempelandOleksij Rempel 18834410ac canfdtest: don't remap SIG to 0
Scripts can be configured to handle different SIGnals and
return codes in different ways. In this case it is better
to forward received signal, instead of converting it to return 0.

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
2018-09-18 11:57:33 +02:00
Marc Kleine-BuddeandGitHub 0ff988eeef Merge pull request #97 from yegorich/travis-warnings
CI: treat gcc warnings as errors
2018-09-18 11:48:23 +02:00
Yegor Yefremov 55b0ba8308 CI: treat gcc warning as errors
For now exclude unused-result warnings in order not to
affect current builds.

Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
2018-09-13 10:38:19 +02:00
Marc Kleine-BuddeandGitHub 7a4dd732af Merge pull request #92 from marckleinebudde/improve-readme
Improve readme
2018-08-17 10:08:46 +02:00
Marc Kleine-Budde db7261d403 README: properly annotate codeblocks 2018-08-17 10:02:02 +02:00
Marc Kleine-Budde 6cedc8a5c6 README: remove stray bullet point 2018-08-17 10:02:02 +02:00
Marc Kleine-Budde d0c855c558 README: replace /home/joel by ~/ 2018-08-17 10:02:02 +02:00
Joel WinarskeandMarc Kleine-Budde 8a3e0453aa CMake first pass (#90)
* CMake first pass

* canbusload dep fix

* Add Eclipse Debug, and Android Studio generation examples

* travis additions

* Update .travis.yml

CMAKE_BUILT_TYPE typo fix

* add android ndk variants(less mips)
2018-08-17 09:50:30 +02:00
Oliver Hartkopp 47f2e7a180 slcand: move setting of loop variable back into code context
With commit 33a9249571 ("slcand: daemonise only once setup is complete")
the daemonize syscall is moved behind serial tty setup.

This patch moves the missing assignment of the loop variable slcand_running
to get it into the code context of the while() loop.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2018-04-29 19:02:55 +02:00
Marc Kleine-BuddeandGitHub 872b73766c Merge pull request #81 from mansr/master
slcand: daemonise only once setup is complete
2018-04-25 16:34:36 +02:00
Mans Rullgard 33a9249571 slcand: daemonise only once setup is complete
Delay the daemon() call until the interface has been configured. This
simplifies scripts that wish to use the new interface immediately.

Signed-off-by: Mans Rullgard <mans@mansr.com>
2018-04-20 13:46:15 +01:00
Marc Kleine-BuddeandGitHub 01041fddd6 Merge pull request #79 from ftheile/consistent-sizeof
Consistent arguments to sizeof().
2018-04-03 14:22:33 +02:00
Frank Theile f51c897d68 Consistent arguments to sizeof().
In calls to functions taking a pointer 'p' and a length 'l':
if a struct variable v is passed in for p, then also pass sizeof(v) for
l.
2018-04-03 11:56:28 +02:00
Oliver HartkoppandGitHub 9d52f81058 Merge pull request #78 from ftheile/patch-1
bzero() is deprecated
2018-03-30 19:03:02 +02:00
Frank TheileandGitHub 6ca4ce8ac9 bzero() is deprecated
Use memset() instead of bzero().
2018-03-30 19:00:05 +02:00
Oliver HartkoppandGitHub 8389744f79 Merge pull request #77 from Shmink/master
valgrind no longer reports uninitialised byte(s) from bind call.
2018-03-24 20:56:57 +01:00
Tom Nicklin b00cb24f12 valgrind no longer reports uninitialised byte(s) from bind call. 2018-03-24 19:53:13 +00:00
65 changed files with 5200 additions and 1622 deletions
+19
View File
@@ -0,0 +1,19 @@
name: C with autotools
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: autogen
run: ./autogen.sh
- name: configure
run: ./configure
- name: make
run: make
- name: make distcheck
run: make distcheck
+5 -3
View File
@@ -32,6 +32,7 @@ GNUmakefile.in
/canlogserver
/canplayer
/cansend
/cansequence
/cansniffer
/isotpdump
/isotpperf
@@ -40,9 +41,10 @@ GNUmakefile.in
/isotpserver
/isotpsniffer
/isotptun
/jacd
/jspy
/jsr
/j1939acd
/j1939cat
/j1939spy
/j1939sr
/log2asc
/log2long
/slcan_attach
+135 -2
View File
@@ -2,6 +2,9 @@ language: c
matrix:
include:
# native
- env: test="x64 4.8.4 (make)"
os: linux
dist: trusty
@@ -12,13 +15,141 @@ matrix:
os: linux
dist: trusty
compiler: gcc
script: ./autogen.sh && ./configure && make distcheck
script: ./autogen.sh && ./configure CFLAGS="-Werror -Wno-unused-result" && make distcheck
- env: test="x64 5.0 (autotools)"
os: linux
dist: trusty
compiler: clang
script: ./autogen.sh && ./configure && make distcheck
script: ./autogen.sh && ./configure CFLAGS="-Werror -Wno-unused-result" && make distcheck
- env: test="x64 4.8.4 (CMake gcc)"
os: linux
dist: trusty
compiler: gcc
before_script:
- mkdir gcc_rel && cd gcc_rel
- cmake ..
script: make
- env: test="x64 5.0 (CMake clang)"
os: linux
dist: trusty
compiler: clang
before_script:
- mkdir clang_rel && cd clang_rel
- cmake ..
script: make
- env: test="x64 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
# 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)"
os: linux
language: android
android:
components:
- build-tools-25.0.2
install:
- echo y | sdkmanager "ndk-bundle"
- echo y | sdkmanager "cmake;3.6.4111459"
before_script:
- export ANDROID_NDK_HOME=$ANDROID_HOME/ndk-bundle
- export ANDROID_CMAKE=$ANDROID_HOME/cmake/3.6.4111459/bin/cmake
- export ANDROID_TOOLCHAIN_FILE=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake
script:
- pushd . && mkdir android15_armeabiv7a_rel && cd android15_armeabiv7a_rel
- $ANDROID_CMAKE -DANDROID_PLATFORM=android-15 -DANDROID_ABI=armeabi-v7a -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=$ANDROID_TOOLCHAIN_FILE ..
- make && popd
- pushd . && mkdir android15_x86_rel && cd android15_x86_rel
- $ANDROID_CMAKE -DANDROID_PLATFORM=android-15 -DANDROID_ABI=x86 -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=$ANDROID_TOOLCHAIN_FILE ..
- make && popd
- pushd . && mkdir android21_arm64-v8a_rel && cd android21_arm64-v8a_rel
- $ANDROID_CMAKE -DANDROID_PLATFORM=android-21 -DANDROID_ABI=arm64-v8a -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=$ANDROID_TOOLCHAIN_FILE ..
- make && popd
- pushd . && mkdir android21_x86_64_rel && cd android21_x86_64_rel
- $ANDROID_CMAKE -DANDROID_PLATFORM=android-21 -DANDROID_ABI=x86_64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=$ANDROID_TOOLCHAIN_FILE ..
- make && popd
- pushd . && mkdir android15_armeabiv7a_dbg && cd android15_armeabiv7a_dbg
- $ANDROID_CMAKE -DANDROID_PLATFORM=android-15 -DANDROID_ABI=armeabi-v7a -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=$ANDROID_TOOLCHAIN_FILE ..
- make && popd
- pushd . && mkdir android15_x86_dbg && cd android15_x86_dbg
- $ANDROID_CMAKE -DANDROID_PLATFORM=android-15 -DANDROID_ABI=x86 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=$ANDROID_TOOLCHAIN_FILE ..
- make && popd
- pushd . && mkdir android21_arm64-v8a_dbg && cd android21_arm64-v8a_dbg
- $ANDROID_CMAKE -DANDROID_PLATFORM=android-21 -DANDROID_ABI=arm64-v8a -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=$ANDROID_TOOLCHAIN_FILE ..
- make && popd
- pushd . && mkdir android21_x86_64_dbg && cd android21_x86_64_dbg
- $ANDROID_CMAKE -DANDROID_PLATFORM=android-21 -DANDROID_ABI=x86_64 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=$ANDROID_TOOLCHAIN_FILE ..
- make && popd
addons:
apt:
@@ -27,5 +158,7 @@ addons:
- automake
- libtool
- m4
- cmake
- ninja-build
sources:
- ubuntu-toolchain-r-test
+150 -2
View File
@@ -1,6 +1,7 @@
LOCAL_PATH := $(call my-dir)
PRIVATE_LOCAL_CFLAGS := -O2 -g -W -Wall \
-Wno-error=unused-parameter \
-DSO_RXQ_OVFL=40 \
-DPF_CAN=29 \
-DAF_CAN=PF_CAN
@@ -15,9 +16,104 @@ LOCAL_SRC_FILES := lib.c canframelen.c
LOCAL_MODULE := libcan
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_STATIC_LIBRARY)
#
# j1939lib
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := libj1939.c
LOCAL_MODULE := libj1939
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_STATIC_LIBRARY)
#
# j1939acd
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := j1939acd.c
LOCAL_MODULE := j1939acd
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libj1939
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
#
# j1939cat
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := j1939cat.c
LOCAL_MODULE := j1939cat
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libj1939
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
#
# j1939spy
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := j1939spy.c
LOCAL_MODULE := j1939spy
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libj1939
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
#
# j1939sr
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := j1939sr.c
LOCAL_MODULE := j1939sr
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libj1939
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
#
# testj1939
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := testj1939.c
LOCAL_MODULE := testj1939
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libj1939
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
#
# candump
#
@@ -30,6 +126,7 @@ LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libcan
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
@@ -45,6 +142,21 @@ 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)
#
# 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)
@@ -59,10 +171,10 @@ LOCAL_MODULE := bcmserver
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
#
# can-calc-bit-timing
#
@@ -74,6 +186,7 @@ LOCAL_MODULE := can-calc-bit-timing
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
@@ -89,6 +202,7 @@ LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libcan
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
@@ -103,6 +217,7 @@ LOCAL_MODULE := canfdtest
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
@@ -118,6 +233,7 @@ LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libcan
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
@@ -132,6 +248,7 @@ LOCAL_MODULE := cangw
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
@@ -147,6 +264,7 @@ LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libcan
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
@@ -162,6 +280,7 @@ LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libcan
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
@@ -176,6 +295,7 @@ LOCAL_MODULE := cansniffer
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
@@ -190,6 +310,7 @@ LOCAL_MODULE := isotpdump
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
@@ -204,6 +325,7 @@ LOCAL_MODULE := isotprecv
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
@@ -218,6 +340,7 @@ LOCAL_MODULE := isotpsend
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
@@ -232,6 +355,7 @@ LOCAL_MODULE := isotpserver
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
@@ -242,10 +366,11 @@ include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := isotpsniffer.c
LOCAL_MODULE := isotpsniffer.c
LOCAL_MODULE := isotpsniffer
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
@@ -260,6 +385,7 @@ LOCAL_MODULE := isotptun
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
@@ -274,6 +400,7 @@ LOCAL_MODULE := isotpperf
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
@@ -289,6 +416,23 @@ LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libcan
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
#
# asc2log
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := asc2log.c
LOCAL_MODULE := asc2log
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libcan
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
@@ -304,6 +448,7 @@ LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libcan
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
@@ -318,6 +463,7 @@ LOCAL_MODULE := slcan_attach
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
@@ -332,6 +478,7 @@ LOCAL_MODULE := slcand
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
@@ -346,5 +493,6 @@ LOCAL_MODULE := slcanpty
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
LOCAL_CFLAGS := $(PRIVATE_LOCAL_CFLAGS)
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)
+98
View File
@@ -0,0 +1,98 @@
cmake_minimum_required(VERSION 3.3)
project(can-utils LANGUAGES C)
include (CheckSymbolExists)
include (GNUInstallDirs)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
check_symbol_exists(__GNU_LIBRARY__ "features.h" _GNU_SOURCE)
if(_GNU_SOURCE)
add_definitions(-D_GNU_SOURCE)
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-parentheses")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-strict-aliasing")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSO_RXQ_OVFL=40")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPF_CAN=29")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DAF_CAN=PF_CAN")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DN_SLCAN=17")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSCM_TIMESTAMPING_OPT_STATS=54")
include_directories (.)
include_directories (./include)
set(PROGRAMS_CANLIB
asc2log
canbusload
candump
cangen
canlogserver
canplayer
cansend
cansequence
log2asc
log2long
)
set(PROGRAMS_J1939
j1939acd
j1939cat
j1939spy
j1939sr
testj1939
)
set(PROGRAMS
${PROGRAMS_CANLIB}
bcmserver
can-calc-bit-timing
canfdtest
cangw
cansniffer
isotpdump
isotpperf
isotprecv
isotpsend
isotpserver
isotpsniffer
isotptun
slcan_attach
slcand
slcanpty
)
if(NOT ANDROID)
list(APPEND PROGRAMS ${PROGRAMS_J1939})
add_library(j1939 STATIC
libj1939.c
)
endif()
add_library(can STATIC
lib.c
canframelen.c
)
foreach(name ${PROGRAMS})
add_executable(${name} ${name}.c)
if("${name}" IN_LIST PROGRAMS_J1939)
target_link_libraries(${name}
PRIVATE j1939
)
elseif("${name}" IN_LIST PROGRAMS_CANLIB)
target_link_libraries(${name}
PRIVATE can
)
endif()
install(TARGETS ${name} DESTINATION ${CMAKE_INSTALL_BINDIR})
endforeach()
ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_SOURCE_DIR}/cmake/make_uninstall.cmake")
+15 -10
View File
@@ -14,16 +14,18 @@ noinst_HEADERS = \
lib.h \
libj1939.h \
terminal.h \
include/linux/can.h \
include/linux/can/bcm.h \
include/linux/can/error.h \
include/linux/can/gw.h \
include/linux/can.h \
include/linux/can/isotp.h \
include/linux/can/j1939.h \
include/linux/can/netlink.h \
include/linux/can/raw.h \
include/linux/can/vxcan.h
include/linux/can/vxcan.h \
include/linux/errqueue.h \
include/linux/net_tstamp.h \
include/linux/netlink.h
noinst_LTLIBRARIES = \
libcan.la \
@@ -48,6 +50,7 @@ bin_PROGRAMS = \
canlogserver \
canplayer \
cansend \
cansequence \
cansniffer \
isotpdump \
isotpperf \
@@ -56,9 +59,10 @@ bin_PROGRAMS = \
isotpserver \
isotpsniffer \
isotptun \
jacd \
jspy \
jsr \
j1939acd \
j1939cat \
j1939spy \
j1939sr \
log2asc \
log2long \
slcan_attach \
@@ -66,9 +70,10 @@ bin_PROGRAMS = \
slcanpty \
testj1939
jacd_LDADD = libj1939.la
jspy_LDADD = libj1939.la
jsr_LDADD = libj1939.la
j1939acd_LDADD = libj1939.la
j1939cat_LDADD = libj1939.la
j1939spy_LDADD = libj1939.la
j1939sr_LDADD = libj1939.la
testj1939_LDADD = libj1939.la
EXTRA_DIST = \
@@ -76,7 +81,7 @@ EXTRA_DIST = \
Android.mk \
README.md \
autogen.sh \
can-j1939-kickstart.md
can-j1939-kickstart.md \
can-j1939.md
MAINTAINERCLEANFILES = \
+27
View File
@@ -0,0 +1,27 @@
Copyright (c) <year> <owner> . All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
+340
View File
@@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
+12
View File
@@ -0,0 +1,12 @@
NOTE! This copyright does *not* cover user programs that use kernel
services by normal system calls - this is merely considered normal use
of the kernel, and does *not* fall under the heading of "derived work".
Also note that the GPL below is copyrighted by the Free Software
Foundation, but the instance of code that it refers to (the Linux
kernel) is copyrighted by me and others who actually wrote it.
Also note that the only valid version of the GPL as far as the kernel
is concerned is _this_ particular version of the license (ie v2, not
v2.2 or v3.x or whatever), unless explicitly otherwise stated.
Linus Torvalds
+79 -42
View File
@@ -41,29 +41,62 @@
DESTDIR ?=
PREFIX ?= /usr/local
MAKEFLAGS = -k
MAKEFLAGS := -k
CFLAGS = -O2 -Wall -Wno-parentheses
CFLAGS := -O2 -Wall -Wno-parentheses
CPPFLAGS += -Iinclude \
-D_FILE_OFFSET_BITS=64 \
-DSO_RXQ_OVFL=40 \
-DPF_CAN=29 \
-DAF_CAN=PF_CAN \
-D_GNU_SOURCE
CPPFLAGS += \
-Iinclude \
-DAF_CAN=PF_CAN \
-DPF_CAN=29 \
-DSO_RXQ_OVFL=40 \
-DSCM_TIMESTAMPING_OPT_STATS=54 \
-D_FILE_OFFSET_BITS=64 \
-D_GNU_SOURCE
PROGRAMS_ISOTP = isotpdump isotprecv isotpsend isotpsniffer isotptun isotpserver isotpperf
PROGRAMS_CANGW = cangw
PROGRAMS_SLCAN = slcan_attach slcand
PROGRAMS_J1939 = jacd jspy jsr testj1939
PROGRAMS = can-calc-bit-timing candump cansniffer cansend canplayer cangen canbusload\
log2long log2asc asc2log\
canlogserver bcmserver\
$(PROGRAMS_ISOTP)\
$(PROGRAMS_CANGW)\
$(PROGRAMS_SLCAN)\
$(PROGRAMS_J1939)\
slcanpty canfdtest
PROGRAMS_CANGW := \
cangw
PROGRAMS_ISOTP := \
isotpdump \
isotpperf \
isotprecv \
isotpsend \
isotpserver \
isotpsniffer \
isotptun
PROGRAMS_J1939 := \
j1939acd \
j1939cat \
j1939spy \
j1939sr \
testj1939
PROGRAMS_SLCAN := \
slcan_attach \
slcand
PROGRAMS := \
$(PROGRAMS_CANGW) \
$(PROGRAMS_ISOTP) \
$(PROGRAMS_J1939) \
$(PROGRAMS_SLCAN) \
asc2log \
bcmserver \
can-calc-bit-timing \
canbusload \
candump \
canfdtest \
cangen \
cansequence \
canlogserver \
canplayer \
cansend \
cansniffer \
log2asc \
log2long \
slcanpty
all: $(PROGRAMS)
@@ -77,31 +110,35 @@ install:
distclean:
rm -f $(PROGRAMS) $(LIBRARIES) *.o *~
cansend.o: lib.h
cangen.o: lib.h
candump.o: lib.h
canplayer.o: lib.h
canlogserver.o: lib.h
canbusload.o: lib.h
log2long.o: lib.h
log2asc.o: lib.h
asc2log.o: lib.h
jacd.o: libj1939.h
jspy.o: libj1939.h
jsr.o: libj1939.h
canbusload.o: lib.h
candump.o: lib.h
cangen.o: lib.h
canlogserver.o: lib.h
canplayer.o: lib.h
cansend.o: lib.h
cansequence.o: lib.h
log2asc.o: lib.h
log2long.o: lib.h
j1939acd.o: libj1939.h
j1939cat.o: libj1939.h
j1939spy.o: libj1939.h
j1939sr.o: libj1939.h
testj1939.o: libj1939.h
canframelen.o: canframelen.h
cansend: cansend.o lib.o
cangen: cangen.o lib.o
candump: candump.o lib.o
canplayer: canplayer.o lib.o
canlogserver: canlogserver.o lib.o
log2long: log2long.o lib.o
log2asc: log2asc.o lib.o
asc2log: asc2log.o lib.o
canbusload: canbusload.o canframelen.o
jacd: jacd.o libj1939.o
jspy: jspy.o libj1939.o
jsr: jsr.o libj1939.o
candump: candump.o lib.o
cangen: cangen.o lib.o
canlogserver: canlogserver.o lib.o
canplayer: canplayer.o lib.o
cansend: cansend.o lib.o
cansequence: cansequence.o lib.o
log2asc: log2asc.o lib.o
log2long: log2long.o lib.o
j1939acd: j1939acd.o libj1939.o
j1939cat: j1939cat.o libj1939.o
j1939spy: j1939spy.o libj1939.o
j1939sr: j1939sr.o libj1939.o
testj1939: testj1939.o libj1939.o
canbusload: canbusload.o canframelen.o
+26 -3
View File
@@ -13,15 +13,17 @@ subsystem (aka SocketCAN):
* canplayer : replay CAN logfiles
* cansend : send a single frame
* 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
* canlogserver : log CAN frames from a remote/local host
* bcmserver : interactive BCM configuration (remote/local)
* [socketcand](https://github.com/dschanoeh/socketcand) : use RAW/BCM/ISO-TP sockets via TCP/IP sockets
* [socketcand](https://github.com/linux-can/socketcand) : use RAW/BCM/ISO-TP sockets via TCP/IP sockets
* [cannelloni](https://github.com/mguentner/cannelloni) : UDP/SCTP based SocketCAN tunnel
#### CAN in-kernel gateway configuration
* cangw : CAN gateway userpace tool for netlink configuration
* cangw : CAN gateway userspace tool for netlink configuration
#### CAN bus measurement and testing
* canbusload : calculate and display the CAN busload
@@ -37,6 +39,16 @@ subsystem (aka SocketCAN):
* isotpperf : ISO15765-2 protocol performance visualisation
* 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
* asc2log : convert ASC logfile to compact CAN frame logfile
* log2asc : convert compact CAN frame logfile to ASC logfile
@@ -47,6 +59,17 @@ subsystem (aka SocketCAN):
* slcand : daemon for serial line CAN interface configuration
* slcanpty : creates a pty for applications using the slcan ASCII protocol
#### CMake Project Generator
* Place your build folder anywhere, passing CMake the path. Relative or absolute.
* Some examples using a build folder under the source tree root:
* Android : ``cmake -DCMAKE_TOOLCHAIN_FILE=~/Android/Sdk/ndk-bundle/build/cmake/android.toolchain.cmake -DANDROID_PLATFORM=android-21 -DANDROID_ABI=armeabi-v7a .. && make``
* Android Studio : Copy repo under your project's ``app`` folder, add ``add_subdirectory(can-utils)`` to your ``CMakeLists.txt`` file after ``cmake_minimum_required()``. Generating project will build Debug/Release for all supported EABI types. ie. arm64-v8a, armeabi-v7a, x86, x86_64.
* Raspberry Pi : ``cmake -DCMAKE_TOOLCHAIN_FILE=~/rpi/tools/build/cmake/rpi.toolchain.cmake .. && make``
* Linux : ``cmake -GNinja .. && ninja``
* Linux Eclipse Photon (Debug) : ``CC=clang cmake -G"Eclipse CDT4 - Unix Makefiles" ../can-utils/ -DCMAKE_BUILD_TYPE=Debug -DCMAKE_ECLIPSE_VERSION=4.8.0``
* To override the base installation directory use: ``CMAKE_INSTALL_PREFIX``
ie. ``CC=clang cmake -DCMAKE_INSTALL_PREFIX=./out .. && make install``
### Additional Information:
* [SocketCAN Documentation (Linux Kernel)](https://www.kernel.org/doc/Documentation/networking/can.txt)
+273 -108
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* asc2log.c - convert ASC logfile to compact CAN frame logfile
*
@@ -41,44 +42,47 @@
*
*/
#include <libgen.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <libgen.h>
#include <unistd.h>
#include <stdlib.h>
#include <locale.h>
#include <net/if.h>
#include <linux/can.h>
#include <linux/can/error.h>
#include <net/if.h>
#include "lib.h"
#define BUFLEN 400 /* CAN FD mode lines can be pretty long */
extern int optind, opterr, optopt;
void print_usage(char *prg)
{
fprintf(stderr, "%s - convert ASC logfile to compact CAN frame logfile.\n", prg);
fprintf(stderr, "Usage: %s\n", prg);
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
fprintf(stderr, " -O <outfile> (default stdout)\n");
fprintf(stderr, "Options:\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)
fprintf(file, "can%d ", dev-1);
else
fprintf(file, "canX ");
/* no CAN FD support so far */
fprint_canframe(file, (struct canfd_frame *)cf, "\n", 0, CAN_MAX_DLEN);
fprint_canframe(file, cf, extra_info, 0, max_dlen);
}
void get_can_id(struct can_frame *cf, char *idstring, int base) {
void get_can_id(struct canfd_frame *cf, char *idstring, int base) {
if (idstring[strlen(idstring)-1] == 'x') {
cf->can_id = CAN_EFF_FLAG;
@@ -121,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) {
char ctmp[10];
int itmp;
struct tm tms;
unsigned int msecs = 0;
if (sscanf(date, "%9s %d %9s %9s %d", ctmp, &itmp, ctmp, ctmp, &itmp) == 5) {
if (strcasestr(date, " pm ") != NULL) {
/* assume EN/US date due to existing am/pm field */
if (!setlocale(LC_TIME, "en_US")) {
@@ -136,29 +350,39 @@ int get_date(struct timeval *tv, char *date) {
return 1;
}
if (!strptime(date, "%B %d %r %Y", &tms))
return 1;
if (!strptime(date, "%B %d %I:%M:%S %p %Y", &tms)) {
/* The string might contain a milliseconds value which strptime()
does not support. So we read the ms value into the year variable
before parsing the real year value (hack) */
if (!strptime(date, "%B %d %I:%M:%S.%Y %p %Y", &tms))
return 1;
sscanf(date, "%*s %*d %*d:%*d:%*d.%3u ", &msecs);
}
} else {
/* assume DE date due to non existing am/pm field */
if (sscanf(date, "%9s %d %9s %d", ctmp, &itmp, ctmp, &itmp) != 4)
return 1;
if (!setlocale(LC_TIME, "de_DE")) {
fprintf(stderr, "Setting locale to 'de_DE' failed!\n");
return 1;
}
if (!strptime(date, "%B %d %T %Y", &tms))
return 1;
if (!strptime(date, "%B %d %H:%M:%S %Y", &tms)) {
/* The string might contain a milliseconds value which strptime()
does not support. So we read the ms value into the year variable
before parsing the real year value (hack) */
if (!strptime(date, "%B %d %H:%M:%S.%Y %Y", &tms))
return 1;
sscanf(date, "%*s %*d %*d:%*d:%*d.%3u ", &msecs);
}
}
//printf("h %d m %d s %d d %d m %d y %d\n",
//tms.tm_hour, tms.tm_min, tms.tm_sec,
//printf("h %d m %d s %d ms %03d d %d m %d y %d\n",
//tms.tm_hour, tms.tm_min, tms.tm_sec, msecs,
//tms.tm_mday, tms.tm_mon+1, tms.tm_year+1900);
tv->tv_sec = mktime(&tms);
tv->tv_usec = msecs * 1000;
if (tv->tv_sec < 0)
return 1;
@@ -168,24 +392,17 @@ int get_date(struct timeval *tv, char *date) {
int main(int argc, char **argv)
{
char buf[100], tmp1[100], tmp2[100];
char buf[BUFLEN], tmp1[BUFLEN], tmp2[BUFLEN];
FILE *infile = stdin;
FILE *outfile = stdout;
static int verbose;
struct can_frame cf;
static struct timeval tv; /* current frame timestamp */
static struct timeval read_tv; /* frame timestamp from ASC file */
static struct timeval tmp_tv; /* tmp frame timestamp from ASC file */
static struct timeval date_tv; /* date of the ASC file */
static int dplace; /* decimal place 4, 5 or 6 or uninitialized */
static char base; /* 'd'ec or 'h'ex */
static char timestamps; /* 'a'bsolute or 'r'elative */
int interface;
char rtr;
int dlc = 0;
int data[8];
int i, found, opt;
int opt;
while ((opt = getopt(argc, argv, "I:O:v?")) != -1) {
switch (opt) {
@@ -223,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 */
@@ -258,87 +475,35 @@ int main(int argc, char **argv)
gettimeofday(&date_tv, NULL);
}
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;
}
/* check for decimal places length in valid CAN frames */
if (sscanf(buf, "%ld.%s %d ", &tv.tv_sec, tmp2, &i) == 3){
dplace = strlen(tmp2);
if (verbose)
printf("decimal place %d, e.g. '%s'\n", dplace, tmp2);
if (dplace < 4 || dplace > 6) {
printf("invalid dplace %d (must be 4, 5 or 6)!\n", dplace);
return 1;
}
} else
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);
if (verbose)
printf("decimal place %d, e.g. '%s'\n", dplace,
tmp2);
if (dplace < 4 || dplace > 6) {
printf("invalid dplace %d (must be 4, 5 or 6)!\n",
dplace);
return 1;
}
}
/* the representation of a valid CAN frame is known here */
/* so try to get CAN frames and ErrorFrames and convert them */
/* 0.002367 1 390x Rx d 8 17 00 14 00 C0 00 08 00 */
found = 0; /* found valid CAN frame ? */
if (base == 'h') { /* check for CAN frames with hexadecimal values */
if (sscanf(buf, "%ld.%ld %d %s %*s %c %d %x %x %x %x %x %x %x %x",
&read_tv.tv_sec, &read_tv.tv_usec, &interface,
tmp1, &rtr, &dlc,
&data[0], &data[1], &data[2], &data[3],
&data[4], &data[5], &data[6], &data[7]
) == dlc + 6 ) {
found = 1;
get_can_id(&cf, tmp1, 16);
}
} else { /* check for CAN frames with decimal values */
if (sscanf(buf, "%ld.%ld %d %s %*s %c %d %d %d %d %d %d %d %d %d",
&read_tv.tv_sec, &read_tv.tv_usec, &interface,
tmp1, &rtr, &dlc,
&data[0], &data[1], &data[2], &data[3],
&data[4], &data[5], &data[6], &data[7]
) == dlc + 6 ) {
found = 1;
get_can_id(&cf, tmp1, 10);
}
}
if (found) {
if (rtr == 'r')
cf.can_id |= CAN_RTR_FLAG;
cf.can_dlc = dlc & 0x0FU;
for (i=0; i<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);
}
/* 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){
if (!strncmp(tmp1, "CANFD", 5))
eval_canfd(buf, &date_tv, timestamps, dplace, outfile);
else
eval_can(buf, &date_tv, timestamps, base, dplace, outfile);
}
}
fclose(outfile);
+19 -15
View File
@@ -1,7 +1,8 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* tst-bcm-server.c
*
* Test programm that implements a socket server which understands ASCII
* Test program that implements a socket server which understands ASCII
* messages for simple broadcast manager frame send commands.
*
* < interface command ival_s ival_us can_id can_dlc [data]* >
@@ -107,20 +108,21 @@
*
*/
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <time.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 <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/bcm.h>
@@ -134,7 +136,7 @@ void childdied(int i)
wait(NULL);
}
int main(int argc, char **argv)
int main(void)
{
int sl, sa, sc;
@@ -179,8 +181,12 @@ int main(int argc, char **argv)
saddr.sin_port = htons(PORT);
while(bind(sl,(struct sockaddr*)&saddr, sizeof(saddr)) < 0) {
struct timespec f = {
.tv_nsec = 100 * 1000 * 1000,
};
printf(".");fflush(NULL);
usleep(100000);
nanosleep(&f, NULL);
}
if (listen(sl,3) != 0) {
@@ -191,11 +197,9 @@ int main(int argc, char **argv)
while (1) {
sa = accept(sl,(struct sockaddr *)&clientaddr, &sin_size);
if (sa > 0 ){
if (fork())
close(sa);
else
if (!fork())
break;
close(sa);
}
else {
if (errno != EINTR) {
+29 -18
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* can-calc-bit-timing.c: Calculate CAN bit timing parameters
*
* Copyright (C) 2008 Wolfgang Grandegger <wg@grandegger.com>
@@ -11,13 +12,13 @@
* email:pisa@cmp.felk.cvut.cz
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
* it under the terms of the version 2 of the GNU General Public License
* as published by the Free Software Foundation
*/
#include <errno.h>
#include <getopt.h>
#include <libgen.h>
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
@@ -25,8 +26,8 @@
#include <stdlib.h>
#include <string.h>
#include <linux/types.h>
#include <linux/can/netlink.h>
#include <linux/types.h>
/* imported from kernel */
@@ -131,17 +132,16 @@ static inline void *netdev_priv(const struct net_device *dev)
static void print_usage(char *cmd)
{
printf("%s - calculate CAN bit timing parameters.\n", cmd);
printf("Usage: %s [options] [<CAN-contoller-name>]\n"
"\tOptions:\n"
"\t-q : don't print header line\n"
"\t-l : list all support CAN controller names\n"
"\t-b <bitrate> : bit-rate in bits/sec\n"
"\t-s <samp_pt> : sample-point in one-tenth of a percent\n"
"Options:\n"
"\t-q don't print header line\n"
"\t-l list all support CAN controller names\n"
"\t-b <bitrate> bit-rate in bits/sec\n"
"\t-s <samp_pt> sample-point in one-tenth of a percent\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);
exit(EXIT_FAILURE);
}
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 best_tseg = 0; /* current best value for tseg */
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;
/* Use CiA recommended sample points */
@@ -638,7 +638,7 @@ int main(int argc, char *argv[])
const struct calc_bittiming_const *btc;
while ((opt = getopt(argc, argv, "b:c:lqs:")) != -1) {
while ((opt = getopt(argc, argv, "b:c:lqs:?")) != -1) {
switch (opt) {
case 'b':
bitrate_nominal = atoi(optarg);
@@ -660,14 +660,22 @@ int main(int argc, char *argv[])
spt_nominal = strtoul(optarg, NULL, 10);
break;
case '?':
print_usage(basename(argv[0]));
exit(EXIT_SUCCESS);
break;
default:
print_usage(argv[0]);
print_usage(basename(argv[0]));
exit(EXIT_FAILURE);
break;
}
}
if (argc > optind + 1)
if (argc > optind + 1) {
print_usage(argv[0]);
exit(EXIT_FAILURE);
}
if (argc == optind + 1)
name = argv[optind];
@@ -677,11 +685,14 @@ int main(int argc, char *argv[])
exit(EXIT_SUCCESS);
}
if (spt_nominal && (spt_nominal >= 1000 || spt_nominal < 100))
if (spt_nominal && (spt_nominal >= 1000 || spt_nominal < 100)) {
print_usage(argv[0]);
exit(EXIT_FAILURE);
}
for (i = 0; i < ARRAY_SIZE(can_calc_consts); i++) {
if (name && strcmp(can_calc_consts[i].bittiming_const.name, name))
if (name &&
strcmp(can_calc_consts[i].bittiming_const.name, name) != 0)
continue;
found = true;
+180
View File
@@ -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 dont 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!
+27 -45
View File
@@ -33,7 +33,7 @@ testj1939 can be told to print the used API calls by adding **-v** program argum
Do in terminal 1
./testj1939 -r can0:
testj1939 -B -r can0
Send raw CAN in terminal 2
@@ -44,7 +44,7 @@ You should have this output in terminal 1
40 02300: 01 23
This means, from NAME 0, SA 40, PGN 02300 was received,
with 2 databytes, *01* & *02*.
with 2 databytes, *01* & *23*.
now emit this CAN message:
@@ -54,20 +54,11 @@ In J1939, this means that ECU 0x40 sends directly to ECU 0x41
Since we did not bind to address 0x41, this traffic
is not meant for us and *testj1939* does not receive it.
### Use source address
Binding a can-j1939 socket to a source address will register
allow you to send packets.
./testj1939 can0:0x80
Your system had, for a small moment, source address 0x80 assigned.
### receive with source address
Terminal 1:
./testj1939 -r can0:0x80
testj1939 -r can0:0x80
Terminal 2:
@@ -87,37 +78,42 @@ Open in terminal 1:
And to these test in another terminal
./testj1939 -s can0:0x80,0x3ffff
testj1939 -B -s can0:0x80 can0:,0x3ffff
This produces **1BFFFF80#0123456789ABCDEF** on CAN.
Note: To be able to send a broadcast we need to use, we need to use "-B" flag.
### Multiple source addresses on 1 CAN device
./testj1939 -s can0:0x90,0x3ffff
testj1939 -B -s can0:0x90 can0:,0x3ffff
produces **1BFFFF90#0123456789ABCDEF** ,
### Use PDU1 PGN
./testj1939 -s can0:0x80,0x12345
testj1939 -B -s can0:0x80 can0:,0x12300
emits **1923FF80#0123456789ABCDEF** .
Note that the real PGN is **0x12300**, and destination address is **0xff**.
Note that the PGN is **0x12300**, and destination address is **0xff**.
### Use destination address info
Since in this example we use unicast source and destination addresses, we do
not need to use "-B" (broadcast) flag.
The destination field may be set during sendto().
*testj1939* implements that like this
./testj1939 -s can0:0x80,0x12345 can0:0x40
testj1939 -s can0:0x80 can0:0x40,0x12300
emits **19234080#0123456789ABCDEF** .
The destination CAN iface __must__ always match the source CAN iface.
Specifing one during bind is therefore sufficient.
Specifying one during bind is therefore sufficient.
./testj1939 -s can0:,0x12300 :0x40
testj1939 -s can0:0x80 :0x40,0x12300
emits the very same.
@@ -129,13 +125,13 @@ __sendto( *peername* )__ , and only one is used.
For broadcasted transmissions
./testj1939 -s can0:0x80,0x12300 :,0x32100
testj1939 -B -s can0:0x80 :,0x32100
emits **1B21FF80#0123456789ABCDEF** rather than 1923FF80#012345678ABCDEF
emits **1B21FF80#0123456789ABCDEF**
Desitination specific transmissions
Destination specific transmissions
./testj1939 -s can0:0x80,0x12300 :0x40,0x32100
testj1939 -s can0:0x80,0x12300 :0x40,0x32100
emits **1B214080#0123456789ABCDEF** .
@@ -146,30 +142,16 @@ It makes sometimes sense to omit the PGN in __bind( *sockname* )__ .
J1939 transparently switches to *Transport Protocol* when packets
do not fit into single CAN packets.
./testj1939 -s20 can0:0x80 :,0x12300
emits:
18ECFF80#20140003FF002301
This is the first fragment for broadcasted *Transport Protocol*.
_testj1939_ returns before the subsequent packets can leave, and
as the last socket on the system closes, can-j1939 effectively
cleans up all resources. Real-world applications will run like forever,
and will not encounter this side-effect.
Try again, and instruct _testj1939_ to keep the socket open for 1 second.
./testj1939 -w1.0 -s20 can0:0x80 :,0x12300
testj1939 -B -s20 can0:0x80 :,0x12300
emits:
18ECFF80#20140003FF002301
18EBFF80#010123456789ABCD
18EBFF80#02EF0123456789AB
18EBFF80#03CDEF01234567
18EBFF80#03CDEF01234567FF
The fragments for broadcasted *Transport Protocol* are seperated
The fragments for broadcasted *Transport Protocol* are separated
__50ms__ from each other.
Destination specific *Transport Protocol* applies flow control
and may emit CAN packets much faster.
@@ -178,11 +160,11 @@ First assign 0x90 to the local system.
This becomes important because the kernel must interact in the
transport protocol sessions before the complete packet is delivered.
./testj1939 can0:0x90 -r &
testj1939 can0:0x90 -r &
Now test:
./testj1939 -s20 can0:0x80 :0x90,0x12300
testj1939 -s20 can0:0x80 :0x90,0x12300
emits:
@@ -190,7 +172,7 @@ emits:
18EC8090#110301FFFF002301
18EB9080#010123456789ABCD
18EB9080#02EF0123456789AB
18EB9080#03CDEF01234567
18EB9080#03CDEF01234567FF
18EC8090#13140003FF002301
The flow control causes a bit overhead.
@@ -200,8 +182,8 @@ This overhead scales very good for larger J1939 packets.
### Change priority of J1939 packets
./testj1939 -s can0:0x80,0x0100
./testj1939 -s -p3 can0:0x80,0x0200
testj1939 -B -s can0:0x80 :,0x0100
testj1939 -B -s -p3 can0:0x80 :,0x0200
emits
+2 -2
View File
@@ -19,7 +19,7 @@ See [Wikipedia:socketcan](http://en.wikipedia.org/wiki/Socketcan)
* CAN id is composed of
* 0..8: SA (source address)
* 9..26:
* PDU1: PGN+DA (destionation address)
* PDU1: PGN+DA (destination address)
* PDU2: PGN
* 27..29: PRIO
@@ -61,7 +61,7 @@ will emit a single CAN frame.
send(sock, data, 9, 0);
will use fragementation, emitting 1+ CAN frames.
will use fragmentation, emitting 1+ CAN frames.
# Using J1939
+24 -21
View File
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* canbusload.c
* canbusload.c - monitor CAN bus load
*
* Copyright (c) 2002-2008 Volkswagen Group Electronic Research
* All rights reserved.
@@ -41,21 +42,21 @@
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#include <libgen.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.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/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <net/if.h>
#include <linux/can.h>
#include <linux/can/raw.h>
@@ -90,23 +91,25 @@ static 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, " (use CTRL-C to terminate %s)\n\n", prg);
fprintf(stderr, "Options: -t (show current time on the first line)\n");
fprintf(stderr, " -c (colorize lines)\n");
fprintf(stderr, " -b (show bargraph in %d%% resolution)\n", PERCENTRES);
fprintf(stderr, " -r (redraw the terminal - similar to top)\n");
fprintf(stderr, " -i (ignore bitstuffing in bandwidth calculation)\n");
fprintf(stderr, " -e (exact calculation of stuffed bits)\n");
fprintf(stderr, "Options:\n");
fprintf(stderr, " -t (show current time on the first line)\n");
fprintf(stderr, " -c (colorize lines)\n");
fprintf(stderr, " -b (show bargraph in %d%% resolution)\n", PERCENTRES);
fprintf(stderr, " -r (redraw the terminal - similar to top)\n");
fprintf(stderr, " -i (ignore bitstuffing in bandwidth calculation)\n");
fprintf(stderr, " -e (exact calculation of stuffed bits)\n");
fprintf(stderr, "\n");
fprintf(stderr, "Up to %d CAN interfaces with mandatory bitrate can be specified on the \n", MAXSOCK);
fprintf(stderr, "commandline in the form: <ifname>@<bitrate>\n\n");
fprintf(stderr, "The bitrate is mandatory as it is needed to know the CAN bus bitrate to\n");
fprintf(stderr, "calcultate the bus load percentage based on the received CAN frames.\n");
fprintf(stderr, "calculate the bus load percentage based on the received CAN frames.\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, "(interface) (received CAN frames) (used bits total) (used bits for payload)\n");
fprintf(stderr, "\nExample:\n");
fprintf(stderr, "\nExamples:\n");
fprintf(stderr, "\nuser$> canbusload can0@100000 can1@500000 can2@500000 can3@500000 -r -t -b -c\n\n");
fprintf(stderr, "%s 2014-02-01 21:13:16 (worst case bitstuffing)\n", prg);
fprintf(stderr, " can0@100000 805 74491 36656 74%% |XXXXXXXXXXXXXX......|\n");
@@ -297,7 +300,7 @@ int main(int argc, char **argv)
ptr = argv[optind+i];
nbytes = strlen(ptr);
if (nbytes >= IFNAMSIZ+sizeof("@1000000")+1) {
if (nbytes >= (int)(IFNAMSIZ+sizeof("@1000000")+1)) {
printf("name of CAN device '%s' is too long!\n", ptr);
return 1;
}
@@ -321,7 +324,7 @@ int main(int argc, char **argv)
nbytes = nptr - ptr; /* interface name is up the first '@' */
if (nbytes >= IFNAMSIZ) {
if (nbytes >= (int)IFNAMSIZ) {
printf("name of CAN device '%s' is too long!\n", ptr);
return 1;
}
@@ -386,14 +389,14 @@ int main(int argc, char **argv)
if (FD_ISSET(s[i], &rdfs)) {
nbytes = read(s[i], &frame, sizeof(struct can_frame));
nbytes = read(s[i], &frame, sizeof(frame));
if (nbytes < 0) {
perror("read");
return 1;
}
if (nbytes < sizeof(struct can_frame)) {
if (nbytes < (int)sizeof(struct can_frame)) {
fprintf(stderr, "read: incomplete CAN frame\n");
return 1;
}
+55 -102
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* candump.c
*
@@ -41,23 +42,23 @@
*
*/
#include <ctype.h>
#include <errno.h>
#include <libgen.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#include <libgen.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/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <net/if.h>
#include <linux/can.h>
#include <linux/can/raw.h>
@@ -115,21 +116,20 @@ static volatile int running = 1;
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, " (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, " -c (increment color mode level)\n");
fprintf(stderr, " -i (binary output - may exceed 80 chars/line)\n");
fprintf(stderr, " -a (enable additional ASCII output)\n");
fprintf(stderr, " -S (swap byte order in printed CAN data[] - marked with '%c' )\n", SWAP_DELIMITER);
fprintf(stderr, " -s <level> (silent mode - %d: off (default) %d: animation %d: silent)\n", SILENT_OFF, SILENT_ANI, SILENT_ON);
fprintf(stderr, " -b <can> (bridge mode - send received frames to <can>)\n");
fprintf(stderr, " -B <can> (bridge mode - like '-b' with disabled loopback)\n");
fprintf(stderr, " -u <usecs> (delay bridge forwarding by <usecs> microseconds)\n");
fprintf(stderr, " -l (log CAN-frames into file. Sets '-s %d' by default)\n", SILENT_ON);
fprintf(stderr, " -L (use log file format on stdout)\n");
fprintf(stderr, " -n <count> (terminate after receiption of <count> CAN frames)\n");
fprintf(stderr, " -n <count> (terminate after reception of <count> CAN frames)\n");
fprintf(stderr, " -r <size> (set socket receive buffer to <size>)\n");
fprintf(stderr, " -D (Don't exit if a \"detected\" can device goes down.\n");
fprintf(stderr, " -d (monitor dropped CAN frames)\n");
@@ -139,22 +139,23 @@ void print_usage(char *prg)
fprintf(stderr, "\n");
fprintf(stderr, "Up to %d CAN interfaces with optional filter sets can be specified\n", MAXSOCK);
fprintf(stderr, "on the commandline in the form: <ifname>[,filter]*\n");
fprintf(stderr, "\nComma 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> (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, " [j|J] (join the given CAN filters - logical AND semantic)\n");
fprintf(stderr, "\nFilters:\n");
fprintf(stderr, " Comma separated filters can be specified for each given CAN interface:\n");
fprintf(stderr, " <can_id>:<can_mask>\n (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>\n (set error frame filter, see include/linux/can/error.h)\n");
fprintf(stderr, " [j|J]\n (join the given CAN filters - logical AND semantic)\n");
fprintf(stderr, "\nCAN IDs, masks and data content are given and expected in hexadecimal values.\n");
fprintf(stderr, "When can_id and can_mask are both 8 digits, they are assumed to be 29 bit EFF.\n");
fprintf(stderr, "When the can_id is 8 digits long the CAN_EFF_FLAG is set for 29 bit EFF format.\n");
fprintf(stderr, "Without any given filter all data frames are received ('0:0' default filter).\n");
fprintf(stderr, "\nUse interface name '%s' to receive from all CAN interfaces.\n", ANYDEV);
fprintf(stderr, "\nExamples:\n");
fprintf(stderr, "%s -c -c -ta can0,123:7FF,400:700,#000000FF can2,400~7F0 can3 can8\n", prg);
fprintf(stderr, "%s -l any,0~0,#FFFFFFFF (log only error frames but no(!) data frames)\n", prg);
fprintf(stderr, "%s -l any,0:0,#FFFFFFFF (log error frames and also all data frames)\n", prg);
fprintf(stderr, "%s vcan2,92345678:DFFFFFFF (match only for extended CAN ID 12345678)\n", prg);
fprintf(stderr, "%s vcan2,123:7FF (matches CAN ID 123 - including EFF and RTR frames)\n", prg);
fprintf(stderr, "%s vcan2,123:C00007FF (matches CAN ID 123 - only SFF and non-RTR frames)\n", prg);
fprintf(stderr, "%s -c -c -ta can0,123:7FF,400:700,#000000FF can2,400~7F0 can3 can8\n\n", prg);
fprintf(stderr, "%s -l any,0~0,#FFFFFFFF\n (log only error frames but no(!) data frames)\n", prg);
fprintf(stderr, "%s -l any,0:0,#FFFFFFFF\n (log error frames and also all data frames)\n", prg);
fprintf(stderr, "%s vcan2,12345678:DFFFFFFF\n (match only for extended CAN ID 12345678)\n", prg);
fprintf(stderr, "%s vcan2,123:7FF\n (matches CAN ID 123 - including EFF and RTR frames)\n", prg);
fprintf(stderr, "%s vcan2,123:C00007FF\n (matches CAN ID 123 - only SFF and non-RTR frames)\n", prg);
fprintf(stderr, "\n");
}
@@ -200,7 +201,7 @@ int idx2dindex(int ifidx, int socket) {
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
perror("SIOCGIFNAME");
if (max_devname_len < strlen(ifr.ifr_name))
if (max_devname_len < (int)strlen(ifr.ifr_name))
max_devname_len = strlen(ifr.ifr_name);
strcpy(devname[i], ifr.ifr_name);
@@ -216,8 +217,6 @@ int main(int argc, char **argv)
{
fd_set rdfs;
int s[MAXSOCK];
int bridge = 0;
useconds_t bridge_delay = 0;
unsigned char timestamp = 0;
unsigned char hwtimestamp = 0;
unsigned char down_causes_exit = 1;
@@ -256,7 +255,7 @@ int main(int argc, char **argv)
last_tv.tv_sec = 0;
last_tv.tv_usec = 0;
while ((opt = getopt(argc, argv, "t:HciaSs:b:B:u:lDdxLn:r:heT:?")) != -1) {
while ((opt = getopt(argc, argv, "t:HciaSs:lDdxLn:r:heT:?")) != -1) {
switch (opt) {
case 't':
timestamp = optarg[0];
@@ -300,49 +299,6 @@ int main(int argc, char **argv)
}
break;
case 'b':
case 'B':
if (strlen(optarg) >= IFNAMSIZ) {
fprintf(stderr, "Name of CAN device '%s' is too long!\n\n", optarg);
return 1;
} else {
bridge = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (bridge < 0) {
perror("bridge socket");
return 1;
}
addr.can_family = AF_CAN;
strcpy(ifr.ifr_name, optarg);
if (ioctl(bridge, SIOCGIFINDEX, &ifr) < 0)
perror("SIOCGIFINDEX");
addr.can_ifindex = ifr.ifr_ifindex;
if (!addr.can_ifindex) {
perror("invalid bridge interface");
return 1;
}
/* disable default receive filter on this write-only RAW socket */
setsockopt(bridge, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
if (opt == 'B') {
const int loopback = 0;
setsockopt(bridge, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
&loopback, sizeof(loopback));
}
if (bind(bridge, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bridge bind");
return 1;
}
}
break;
case 'u':
bridge_delay = (useconds_t)strtoul(optarg, (char **)NULL, 10);
break;
case 'l':
log = 1;
break;
@@ -461,7 +417,7 @@ int main(int argc, char **argv)
printf("using interface name '%s'.\n", ifr.ifr_name);
#endif
if (strcmp(ANYDEV, ifr.ifr_name)) {
if (strcmp(ANYDEV, ifr.ifr_name) != 0) {
if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX");
exit(1);
@@ -502,12 +458,16 @@ int main(int argc, char **argv)
&rfilter[numfilter].can_id,
&rfilter[numfilter].can_mask) == 2) {
rfilter[numfilter].can_mask &= ~CAN_ERR_FLAG;
if (*(ptr+8) == ':')
rfilter[numfilter].can_id |= CAN_EFF_FLAG;
numfilter++;
} else if (sscanf(ptr, "%x~%x",
&rfilter[numfilter].can_id,
&rfilter[numfilter].can_mask) == 2) {
rfilter[numfilter].can_id |= CAN_INV_FILTER;
rfilter[numfilter].can_mask &= ~CAN_ERR_FLAG;
if (*(ptr+8) == '~')
rfilter[numfilter].can_id |= CAN_EFF_FLAG;
numfilter++;
} else if (*ptr == 'j' || *ptr == 'J') {
join_filter = 1;
@@ -612,7 +572,7 @@ int main(int argc, char **argv)
if (log) {
time_t currtime;
struct tm now;
char fname[sizeof("candump-2006-11-20_202026.log")+1];
char fname[83]; /* suggested by -Wformat-overflow= */
if (time(&currtime) == (time_t)-1) {
perror("time");
@@ -630,9 +590,9 @@ int main(int argc, char **argv)
now.tm_sec);
if (silent != SILENT_ON)
printf("\nWarning: console output active while logging!");
fprintf(stderr, "Warning: Console output active while logging!\n");
fprintf(stderr, "\nEnabling Logfile '%s'\n\n", fname);
fprintf(stderr, "Enabling Logfile '%s'\n", fname);
logfile = fopen(fname, "w");
if (!logfile) {
@@ -668,6 +628,7 @@ int main(int argc, char **argv)
if (FD_ISSET(s[i], &rdfs)) {
int idx;
char *extra_info = "";
/* these settings may be modified by recvmsg() */
iov.iov_len = sizeof(frame);
@@ -698,20 +659,6 @@ int main(int argc, char **argv)
if (count && (--count == 0))
running = 0;
if (bridge) {
if (bridge_delay)
usleep(bridge_delay);
nbytes = write(bridge, &frame, nbytes);
if (nbytes < 0) {
perror("bridge write");
return 1;
} else if ((size_t)nbytes != CAN_MTU && (size_t)nbytes != CANFD_MTU) {
fprintf(stderr,"bridge write: incomplete CAN frame\n");
return 1;
}
}
for (cmsg = CMSG_FIRSTHDR(&msg);
cmsg && (cmsg->cmsg_level == SOL_SOCKET);
@@ -755,24 +702,33 @@ int main(int argc, char **argv)
if (frame.can_id & CAN_EFF_FLAG)
view |= CANLIB_VIEW_INDENT_SFF;
if (extra_msg_info) {
if (msg.msg_flags & MSG_DONTROUTE)
extra_info = " T";
else
extra_info = " R";
}
if (log) {
char buf[CL_CFSZ]; /* max length */
/* log CAN frame with absolute timestamp & device */
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,
max_devname_len, devname[idx], buf);
max_devname_len, devname[idx], buf,
extra_info);
}
if (logfrmt) {
if ((logfrmt) && (silent == SILENT_OFF)){
char buf[CL_CFSZ]; /* max length */
/* print CAN frame in log file style to stdout */
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,
max_devname_len, devname[idx], buf);
max_devname_len, devname[idx], buf,
extra_info);
goto out_fflush; /* no other output to stdout */
}
@@ -789,7 +745,7 @@ int main(int argc, char **argv)
switch (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;
case 'A': /* absolute with date */
@@ -799,7 +755,7 @@ int main(int argc, char **argv)
tm = *localtime(&tv.tv_sec);
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;
@@ -816,7 +772,7 @@ int main(int argc, char **argv)
diff.tv_sec--, diff.tv_usec += 1000000;
if (diff.tv_sec < 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')
last_tv = tv; /* update for delta calculation */
@@ -854,9 +810,6 @@ int main(int argc, char **argv)
for (i=0; i<currmax; i++)
close(s[i]);
if (bridge)
close(bridge);
if (log)
fclose(logfile);
+169 -77
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* canfdtest.c - Full-duplex test program (DUT and host part)
*
@@ -5,9 +6,8 @@
* (C) 2009 Wolfgang Grandegger <wg@grandegger.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
* it under the terms of the version 2 of the GNU General Public License
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -17,23 +17,24 @@
* 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 <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <libgen.h>
#include <getopt.h>
#include <time.h>
#include <sched.h>
#include <limits.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/ioctl.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/raw.h>
@@ -47,71 +48,78 @@ static int running = 1;
static int verbose;
static int sockfd;
static int test_loops;
static int exit_sig;
static int inflight_count = CAN_MSG_COUNT;
static void print_usage(char *prg)
{
fprintf(stderr,
"%s - Full-duplex test program (DUT and host part).\n"
"Usage: %s [options] <can-interface>\n"
"\n"
"Options: -v (low verbosity)\n"
"Options:\n"
" -v (low verbosity)\n"
" -vv (high verbosity)\n"
" -g (generate messages)\n"
" -l COUNT (test loop count)\n"
" -f COUNT (number of frames in flight, default: %d)\n"
"\n"
"With the option '-g' CAN messages are generated and checked\n"
"on <can-interface>, otherwise all messages received on the\n"
"<can-interface> are sent back incrementing the CAN id and\n"
"all data bytes. The program can be aborted with ^C.\n"
"\n"
"Example:\n"
"\ton DUT : %s -v can0\n"
"\ton Host: %s -g -v can2\n",
prg, prg, prg);
"Examples:\n"
"\ton DUT:\n"
"%s -v can0\n"
"\ton Host:\n"
"%s -g -v can2\n",
prg, prg, CAN_MSG_COUNT, prg, prg);
exit(1);
}
static void print_frame(struct can_frame *frame)
static void print_frame(const struct can_frame *frame, int inc)
{
int i;
printf("%04x: ", frame->can_id);
printf("%04x: ", frame->can_id + inc);
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(" %02x", (uint8_t)(frame->data[i] + inc));
}
printf("\n");
}
static void print_compare(struct can_frame *exp, struct can_frame *rec)
static void print_compare(const struct can_frame *exp, const struct can_frame *rec, int inc)
{
printf("expected: ");
print_frame(exp);
print_frame(exp, inc);
printf("received: ");
print_frame(rec);
print_frame(rec, 0);
}
static void compare_frame(struct can_frame *exp, struct can_frame *rec)
static void compare_frame(struct can_frame *exp, struct can_frame *rec, int inc)
{
int i;
if (rec->can_id != exp->can_id) {
if (rec->can_id != exp->can_id + inc) {
printf("Message ID mismatch!\n");
print_compare(exp, rec);
print_compare(exp, rec, inc);
running = 0;
} else if (rec->can_dlc != exp->can_dlc) {
printf("Message length mismatch!\n");
print_compare(exp, rec);
print_compare(exp, rec, inc);
running = 0;
} else {
for (i = 0; i < rec->can_dlc; i++) {
if (rec->data[i] != exp->data[i]) {
printf("Databyte %x mismatch !\n", i);
if (rec->data[i] != (uint8_t)(exp->data[i] + inc)) {
printf("Databyte %x mismatch!\n", i);
print_compare(exp,
rec);
rec, inc);
running = 0;
}
}
@@ -149,6 +157,7 @@ static void signal_handler(int signo)
{
close(sockfd);
running = 0;
exit_sig = signo;
}
static int recv_frame(struct can_frame *frame)
@@ -172,29 +181,63 @@ static int send_frame(struct can_frame *frame)
while ((ret = send(sockfd, frame, sizeof(*frame), 0))
!= sizeof(*frame)) {
if (ret < 0) {
if (errno != ENOBUFS) {
perror("send failed");
return -1;
} else {
if (verbose) {
printf("N");
fflush(stdout);
}
}
} else {
if (ret >= 0) {
fprintf(stderr, "send returned %d", ret);
return -1;
}
if (errno != ENOBUFS) {
perror("send failed");
return -1;
}
if (verbose) {
printf("N");
fflush(stdout);
}
}
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)
{
unsigned int frame_count = 0;
struct can_frame frame;
int i;
while (running) {
if (recv_frame(&frame))
@@ -203,19 +246,11 @@ static int can_echo_dut(void)
if (verbose == 1) {
echo_progress(frame.data[0]);
} else if (verbose > 1) {
printf("%04x: ", frame.can_id);
if (frame.can_id & CAN_RTR_FLAG) {
printf("remote request");
} else {
printf("[%d]", frame.can_dlc);
for (i = 0; i < frame.can_dlc; i++)
printf(" %02x", frame.data[i]);
}
printf("\n");
print_frame(&frame, 0);
}
frame.can_id++;
for (i = 0; i < frame.can_dlc; i++)
frame.data[i]++;
check_frame(&frame);
inc_frame(&frame);
if (send_frame(&frame))
return -1;
@@ -234,29 +269,40 @@ static int can_echo_dut(void)
static int can_echo_gen(void)
{
struct can_frame tx_frames[CAN_MSG_COUNT];
struct can_frame *tx_frames;
int *recv_tx;
struct can_frame rx_frame;
unsigned char counter = 0;
int send_pos = 0, recv_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;
tx_frames = calloc(inflight_count, sizeof(* tx_frames));
if (!tx_frames)
return -1;
recv_tx = calloc(inflight_count, sizeof(* recv_tx));
if (!recv_tx) {
err = -1;
goto out_free_tx_frames;
}
while (running) {
if (unprocessed < CAN_MSG_COUNT) {
if (unprocessed < inflight_count) {
/* still send messages */
tx_frames[send_pos].can_dlc = CAN_MSG_LEN;
tx_frames[send_pos].can_id = CAN_MSG_ID;
recv_tx[send_pos] = 0;
for (i = 0; i < CAN_MSG_LEN; i++)
tx_frames[send_pos].data[i] = counter + i;
if (send_frame(&tx_frames[send_pos]))
return -1;
/* increment to be equal to expected */
tx_frames[send_pos].can_id++;
for (i = 0; i < CAN_MSG_LEN; i++)
tx_frames[send_pos].data[i]++;
if (send_frame(&tx_frames[send_pos])) {
err = -1;
goto out_free;
}
send_pos++;
if (send_pos == CAN_MSG_COUNT)
if (send_pos == inflight_count)
send_pos = 0;
unprocessed++;
if (verbose == 1)
@@ -268,29 +314,51 @@ static int can_echo_gen(void)
else
millisleep(1);
} else {
if (recv_frame(&rx_frame))
return -1;
if (recv_frame(&rx_frame)) {
err = -1;
goto out_free;
}
if (verbose > 1)
print_frame(&rx_frame);
print_frame(&rx_frame, 0);
/* own frame */
if (rx_frame.can_id == CAN_MSG_ID) {
compare_frame(&tx_frames[recv_tx_pos], &rx_frame, 0);
recv_tx[recv_tx_pos] = 1;
recv_tx_pos++;
if (recv_tx_pos == inflight_count)
recv_tx_pos = 0;
continue;
}
if (!recv_tx[recv_rx_pos]) {
printf("RX before TX!\n");
print_frame(&rx_frame, 0);
running = 0;
}
/* compare with expected */
compare_frame(&tx_frames[recv_pos], &rx_frame);
compare_frame(&tx_frames[recv_rx_pos], &rx_frame, 1);
recv_rx_pos++;
if (recv_rx_pos == inflight_count)
recv_rx_pos = 0;
loops++;
if (test_loops && loops >= test_loops)
break;
recv_pos++;
if (recv_pos == CAN_MSG_COUNT)
recv_pos = 0;
unprocessed--;
}
}
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[])
@@ -300,25 +368,30 @@ int main(int argc, char *argv[])
int family = PF_CAN, type = SOCK_RAW, proto = CAN_RAW;
int echo_gen = 0;
int opt, err;
int recv_own_msgs = 1;
signal(SIGTERM, signal_handler);
signal(SIGHUP, signal_handler);
signal(SIGINT, signal_handler);
while ((opt = getopt(argc, argv, "gl:v")) != -1) {
while ((opt = getopt(argc, argv, "f:gl:v?")) != -1) {
switch (opt) {
case 'v':
verbose++;
break;
case 'f':
inflight_count = atoi(optarg);
break;
case 'l':
test_loops = atoi(optarg);;
test_loops = atoi(optarg);
break;
case 'g':
echo_gen = 1;
break;
case '?':
default:
print_usage(basename(argv[0]));
break;
@@ -337,8 +410,21 @@ int main(int argc, char *argv[])
return 1;
}
if (echo_gen) {
if (setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,
&recv_own_msgs, sizeof(recv_own_msgs)) == -1) {
perror("setsockopt");
return 1;
}
}
addr.can_family = family;
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) {
perror("bind");
@@ -355,5 +441,11 @@ int main(int argc, char *argv[])
printf("Exiting...\n");
close(sockfd);
if (exit_sig) {
signal(exit_sig, SIG_DFL);
kill(getpid(), exit_sig);
}
return err;
}
+8 -6
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* canframelen.c
*
@@ -43,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 <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "canframelen.h"
/**
* Functions and types for CRC checks.
+1
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* canframelen.h
*
+63 -35
View File
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* cangen.c - CAN frames generator for testing purposes
* cangen.c - CAN frames generator
*
* Copyright (c) 2002-2007 Volkswagen Group Electronic Research
* All rights reserved.
@@ -41,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 <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <poll.h>
#include <ctype.h>
#include <libgen.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/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <net/if.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include "lib.h"
#define DEFAULT_GAP 200 /* ms */
#define DEFAULT_BURST_COUNT 1
#define MODE_RANDOM 0
#define MODE_INCREMENT 1
@@ -77,17 +80,20 @@ static unsigned long long enobufs_count;
void print_usage(char *prg)
{
fprintf(stderr, "\n%s: generate CAN frames\n\n", prg);
fprintf(stderr, "%s - CAN frames generator.\n\n", prg);
fprintf(stderr, "Usage: %s [options] <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);
fprintf(stderr, " -e (generate extended frame mode "
"(EFF) CAN frames)\n");
fprintf(stderr, " -f (generate CAN FD CAN frames)\n");
fprintf(stderr, " -b (generate CAN FD CAN frames"
" with bitrate switch (BRS))\n");
fprintf(stderr, " -E (generate CAN FD CAN frames"
" with error state (ESI))\n");
fprintf(stderr, " -R (send RTR frame)\n");
fprintf(stderr, " -m (mix -e -f -b -R frames)\n");
fprintf(stderr, " -m (mix -e -f -b -E -R frames)\n");
fprintf(stderr, " -I <mode> (CAN ID"
" generation mode - see below)\n");
fprintf(stderr, " -L <mode> (CAN data length code (dlc)"
@@ -102,28 +108,30 @@ void print_usage(char *prg)
" write() syscalls)\n");
fprintf(stderr, " -x (disable local loopback of "
"generated CAN frames)\n");
fprintf(stderr, " -c (number of messages to send in burst, "
"default 1)\n");
fprintf(stderr, " -v (increment verbose level for "
"printing sent CAN frames)\n\n");
fprintf(stderr, "Generation modes:\n");
fprintf(stderr, "'r' => random values (default)\n");
fprintf(stderr, "'i' => increment values\n");
fprintf(stderr, "<hexvalue> => fix value using <hexvalue>\n\n");
fprintf(stderr, " 'r' => random values (default)\n");
fprintf(stderr, " 'i' => increment values\n");
fprintf(stderr, " <hexvalue> => fix value using <hexvalue>\n\n");
fprintf(stderr, "When incrementing the CAN data the data length code "
"minimum is set to 1.\n");
fprintf(stderr, "CAN IDs and data content are given and expected in hexadecimal values.\n\n");
fprintf(stderr, "Examples:\n");
fprintf(stderr, "%s vcan0 -g 4 -I 42A -L 1 -D i -v -v ", prg);
fprintf(stderr, "(fixed CAN ID and length, inc. data)\n");
fprintf(stderr, "%s vcan0 -e -L i -v -v -v ", prg);
fprintf(stderr, "(generate EFF frames, incr. length)\n");
fprintf(stderr, "%s vcan0 -D 11223344DEADBEEF -L 8 ", prg);
fprintf(stderr, "(fixed CAN data payload and length)\n");
fprintf(stderr, "%s vcan0 -g 0 -i -x ", prg);
fprintf(stderr, "(full load test ignoring -ENOBUFS)\n");
fprintf(stderr, "%s vcan0 -g 0 -p 10 -x ", prg);
fprintf(stderr, "(full load test with polling, 10ms timeout)\n");
fprintf(stderr, "%s vcan0 ", prg);
fprintf(stderr, "(my favourite default :)\n\n");
fprintf(stderr, "%s vcan0 -g 4 -I 42A -L 1 -D i -v -v\n", prg);
fprintf(stderr, "\t(fixed CAN ID and length, inc. data)\n");
fprintf(stderr, "%s vcan0 -e -L i -v -v -v\n", prg);
fprintf(stderr, "\t(generate EFF frames, incr. length)\n");
fprintf(stderr, "%s vcan0 -D 11223344DEADBEEF -L 8\n", prg);
fprintf(stderr, "\t(fixed CAN data payload and length)\n");
fprintf(stderr, "%s vcan0 -g 0 -i -x\n", prg);
fprintf(stderr, "\t(full load test ignoring -ENOBUFS)\n");
fprintf(stderr, "%s vcan0 -g 0 -p 10 -x\n", prg);
fprintf(stderr, "\t(full load test with polling, 10ms timeout)\n");
fprintf(stderr, "%s vcan0\n", prg);
fprintf(stderr, "\t(my favourite default :)\n\n");
}
void sigterm(int signo)
@@ -134,11 +142,13 @@ void sigterm(int signo)
int main(int argc, char **argv)
{
double gap = DEFAULT_GAP;
unsigned long burst_count = DEFAULT_BURST_COUNT;
unsigned long polltimeout = 0;
unsigned char ignore_enobufs = 0;
unsigned char extended = 0;
unsigned char canfd = 0;
unsigned char brs = 0;
unsigned char esi = 0;
unsigned char mix = 0;
unsigned char id_mode = MODE_RANDOM;
unsigned char data_mode = MODE_RANDOM;
@@ -147,6 +157,7 @@ int main(int argc, char **argv)
unsigned char verbose = 0;
unsigned char rtr_frame = 0;
int count = 0;
unsigned long burst_sent_count = 0;
int mtu, maxdlen;
uint64_t incdata = 0;
int incdlc = 0;
@@ -174,7 +185,7 @@ int main(int argc, char **argv)
signal(SIGHUP, sigterm);
signal(SIGINT, sigterm);
while ((opt = getopt(argc, argv, "ig:ebfmI:L:D:xp:n:vRh?")) != -1) {
while ((opt = getopt(argc, argv, "ig:ebEfmI:L:D:xp:n:c:vRh?")) != -1) {
switch (opt) {
case 'i':
@@ -198,6 +209,11 @@ int main(int argc, char **argv)
canfd = 1;
break;
case 'E':
esi = 1; /* error state indicator implies CAN FD */
canfd = 1;
break;
case 'm':
mix = 1;
canfd = 1; /* to switch the socket into CAN FD mode */
@@ -239,6 +255,10 @@ int main(int argc, char **argv)
}
break;
case 'c':
burst_count = strtoul(optarg, NULL, 10);
break;
case 'v':
verbose++;
break;
@@ -278,7 +298,7 @@ int main(int argc, char **argv)
}
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 */
if (id_mode == MODE_FIX && frame.can_id > 0x7FF && !extended) {
@@ -368,6 +388,8 @@ int main(int argc, char **argv)
maxdlen = CANFD_MAX_DLEN;
if (brs)
frame.flags |= CANFD_BRS;
if (esi)
frame.flags |= CANFD_ESI;
} else {
mtu = CAN_MTU;
maxdlen = CAN_MAX_DLEN;
@@ -447,8 +469,8 @@ resend:
if (poll(&fds, 1, polltimeout) < 0) {
perror("poll");
return 1;
} else
goto resend;
}
goto resend;
} else
enobufs_count++;
@@ -457,10 +479,14 @@ resend:
return 1;
}
if (gap) /* gap == 0 => performance test :-] */
burst_sent_count++;
if (gap && burst_sent_count >= burst_count) /* gap == 0 => performance test :-] */
if (nanosleep(&ts, NULL))
return 1;
if (burst_sent_count >= burst_count)
burst_sent_count = 0;
if (id_mode == MODE_INCREMENT)
frame.can_id++;
@@ -489,8 +515,10 @@ resend:
i = random();
extended = i&1;
canfd = i&2;
if (canfd)
if (canfd) {
brs = i&4;
esi = i&8;
}
rtr_frame = ((i&24) == 24); /* reduce RTR frames to 1/4 */
}
}
+233 -64
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* cangw.c - manage PF_CAN netlink gateway
*
@@ -41,17 +42,17 @@
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <libgen.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <net/if.h>
#include <libgen.h>
#include <linux/can/gw.h>
#include <linux/netlink.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 {
UNSPEC,
@@ -67,13 +68,19 @@ struct modattr {
__u8 instruction;
} __attribute__((packed));
struct fdmodattr {
struct canfd_frame cf;
__u8 modtype;
__u8 instruction;
} __attribute__((packed));
#define RTCAN_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct rtcanmsg))))
#define RTCAN_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct rtcanmsg))
/* some netlink helpers stolen from iproute2 package */
#define NLMSG_TAIL(nmsg) \
((struct rtattr *)(((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
((struct rtattr *)(((char *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
int alen)
@@ -81,7 +88,7 @@ int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
int len = RTA_LENGTH(alen);
struct rtattr *rta;
if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
if ((int)(NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len)) > maxlen) {
fprintf(stderr, "addattr_l: message exceeded bound of %d\n",
maxlen);
return -1;
@@ -124,7 +131,36 @@ void printmod(const char *type, const void *data)
printf(":%03X.%X.", mod.cf.can_id, mod.cf.can_dlc);
for (i = 0; i < 8; i++)
for (i = 0; i < CAN_MAX_DLEN; i++)
printf("%02X", mod.cf.data[i]);
printf(" ");
}
void printfdmod(const char *type, const void *data)
{
struct fdmodattr mod;
int i;
memcpy (&mod, data, CGW_FDMODATTR_LEN);
printf("-M %s:", type);
if (mod.modtype & CGW_MOD_ID)
printf("I");
if (mod.modtype & CGW_MOD_FLAGS)
printf("F");
if (mod.modtype & CGW_MOD_LEN)
printf("L");
if (mod.modtype & CGW_MOD_DATA)
printf("D");
printf(":%03X.%X.%X.", mod.cf.can_id, mod.cf.flags, mod.cf.len);
for (i = 0; i < CANFD_MAX_DLEN; i++)
printf("%02X", mod.cf.data[i]);
printf(" ");
@@ -186,45 +222,60 @@ void print_cs_crc8(struct cgw_csum_crc8 *cs_crc8)
void print_usage(char *prg)
{
fprintf(stderr, "%s - manage PF_CAN netlink gateway.\n", prg);
fprintf(stderr, "\nUsage: %s [options]\n\n", prg);
fprintf(stderr, "Commands: -A (add a new rule)\n");
fprintf(stderr, " -D (delete a rule)\n");
fprintf(stderr, " -F (flush / delete all rules)\n");
fprintf(stderr, " -L (list all rules)\n");
fprintf(stderr, "Mandatory: -s <src_dev> (source netdevice)\n");
fprintf(stderr, " -d <dst_dev> (destination netdevice)\n");
fprintf(stderr, "Options: -t (preserve src_dev rx timestamp)\n");
fprintf(stderr, " -e (echo sent frames - recommended on vcanx)\n");
fprintf(stderr, " -i (allow to route to incoming interface)\n");
fprintf(stderr, " -u <uid> (user defined modification identifier)\n");
fprintf(stderr, " -l <hops> (limit the number of frame hops / routings)\n");
fprintf(stderr, " -f <filter> (set CAN filter)\n");
fprintf(stderr, " -m <mod> (set frame modifications)\n");
fprintf(stderr, " -x <from_idx>:<to_idx>:<result_idx>:<init_xor_val> (XOR checksum)\n");
fprintf(stderr, " -c <from>:<to>:<result>:<init_val>:<xor_val>:<crctab[256]> (CRC8 cs)\n");
fprintf(stderr, " -p <profile>:[<profile_data>] (CRC8 checksum profile & parameters)\n");
fprintf(stderr, "Commands:\n");
fprintf(stderr, " -A (add a new rule)\n");
fprintf(stderr, " -D (delete a rule)\n");
fprintf(stderr, " -F (flush / delete all rules)\n");
fprintf(stderr, " -L (list all rules)\n");
fprintf(stderr, "Mandatory:\n");
fprintf(stderr, " -s <src_dev> (source netdevice)\n");
fprintf(stderr, " -d <dst_dev> (destination netdevice)\n");
fprintf(stderr, "Options:\n");
fprintf(stderr, " -X (this is a CAN FD rule)\n");
fprintf(stderr, " -t (preserve src_dev rx timestamp)\n");
fprintf(stderr, " -e (echo sent frames - recommended on vcanx)\n");
fprintf(stderr, " -i (allow to route to incoming interface)\n");
fprintf(stderr, " -u <uid> (user defined modification identifier)\n");
fprintf(stderr, " -l <hops> (limit the number of frame hops / routings)\n");
fprintf(stderr, " -f <filter> (set CAN filter)\n");
fprintf(stderr, " -m <mod> (set Classic CAN frame modifications)\n");
fprintf(stderr, " -M <MOD> (set CAN FD frame modifications)\n");
fprintf(stderr, " -x <from_idx>:<to_idx>:<result_idx>:<init_xor_val> (XOR checksum)\n");
fprintf(stderr, " -c <from>:<to>:<result>:<init_val>:<xor_val>:<crctab[256]> (CRC8 cs)\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, "\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, "<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, "\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> 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_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_data> is always eight(!) u8 values containing the CAN frames data\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_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_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, "<instruction>:<canfd_frame-elements>:<can_id>.<flags>.<len>.<can_data>\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, " <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, " <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, "The max. four modifications are performed in the order AND -> OR -> XOR -> SET\n");
fprintf(stderr, "\n");
fprintf(stderr, "Example:\n");
fprintf(stderr, "%s -A -s can0 -d vcan3 -e -f 123:C00007FF -m SET:IL:333.4.1122334455667788\n", prg);
fprintf(stderr, "\n");
fprintf(stderr, "Supported CRC 8 profiles:\n");
fprintf(stderr, "Profile '%d' (1U8) - add one additional u8 value\n", CGW_CRC8PRF_1U8);
fprintf(stderr, "Profile '%d' (16U8) - add u8 value from table[16] indexed by (data[1] & 0xF)\n", CGW_CRC8PRF_16U8);
fprintf(stderr, "Profile '%d' (SFFID_XOR) - add u8 value (can_id & 0xFF) ^ (can_id >> 8 & 0xFF)\n", CGW_CRC8PRF_SFFID_XOR);
fprintf(stderr, " Profile '%d' (1U8) add one additional u8 value\n", CGW_CRC8PRF_1U8);
fprintf(stderr, " Profile '%d' (16U8) add u8 value from table[16] indexed by (data[1] & 0xF)\n", CGW_CRC8PRF_16U8);
fprintf(stderr, " Profile '%d' (SFFID_XOR) add u8 value (can_id & 0xFF) ^ (can_id >> 8 & 0xFF)\n", CGW_CRC8PRF_SFFID_XOR);
fprintf(stderr, "\n");
fprintf(stderr, "Examples:\n");
fprintf(stderr, "%s -A -s can0 -d vcan3 -e -f 123:C00007FF -m SET:IL:333.4.1122334455667788\n", prg);
fprintf(stderr, "\n");
}
@@ -244,14 +295,14 @@ int parse_crc8_profile(char *optarg, struct cgw_csum_crc8 *crc8)
int ret = 1;
char *ptr;
if (sscanf(optarg, "%hhd:", &crc8->profile) != 1)
if (sscanf(optarg, "%hhu:", &crc8->profile) != 1)
return ret;
switch (crc8->profile) {
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;
break;
@@ -281,7 +332,8 @@ int parse_crc8_profile(char *optarg, struct cgw_csum_crc8 *crc8)
int parse_mod(char *optarg, struct modattr *modmsg)
{
char *ptr, *nptr;
char hexdata[17] = {0};
char hexdata[(CAN_MAX_DLEN * 2) + 1] = {0};
canid_t can_id;
ptr = optarg;
nptr = strchr(ptr, ':');
@@ -330,30 +382,97 @@ int parse_mod(char *optarg, struct modattr *modmsg)
ptr++;
}
if (sscanf(++ptr, "%x.%hhx.%16s", &modmsg->cf.can_id,
if (sscanf(++ptr, "%x.%hhx.%16s", &can_id,
(unsigned char *)&modmsg->cf.can_dlc, hexdata) != 3)
return 5;
/* 4-bit masks can have values from 0 to 0xF */
if (modmsg->cf.can_dlc > 0xF)
modmsg->cf.can_id = can_id;
if (strlen(hexdata) != (CAN_MAX_DLEN * 2))
return 6;
/* but when setting CAN_DLC the value has to be limited to 8 */
if (modmsg->instruction == CGW_MOD_SET && modmsg->cf.can_dlc > 8)
if (b64hex(hexdata, &modmsg->cf.data[0], CAN_MAX_DLEN))
return 7;
if (strlen(hexdata) != 16)
return 8;
return 0; /* ok */
}
if (b64hex(hexdata, &modmsg->cf.data[0], 8))
return 9;
int parse_fdmod(char *optarg, struct fdmodattr *modmsg)
{
char *ptr, *nptr;
char hexdata[(CANFD_MAX_DLEN * 2) + 1] = {0};
canid_t can_id;
ptr = optarg;
nptr = strchr(ptr, ':');
if ((nptr - ptr > 3) || (nptr - ptr == 0))
return 1;
if (!strncmp(ptr, "AND", 3))
modmsg->instruction = CGW_FDMOD_AND;
else if (!strncmp(ptr, "OR", 2))
modmsg->instruction = CGW_FDMOD_OR;
else if (!strncmp(ptr, "XOR", 3))
modmsg->instruction = CGW_FDMOD_XOR;
else if (!strncmp(ptr, "SET", 3))
modmsg->instruction = CGW_FDMOD_SET;
else
return 2;
ptr = nptr+1;
nptr = strchr(ptr, ':');
if ((nptr - ptr > 4) || (nptr - ptr == 0))
return 3;
modmsg->modtype = 0;
while (*ptr != ':') {
switch (*ptr) {
case 'I':
modmsg->modtype |= CGW_MOD_ID;
break;
case 'F':
modmsg->modtype |= CGW_MOD_FLAGS;
break;
case 'L':
modmsg->modtype |= CGW_MOD_LEN;
break;
case 'D':
modmsg->modtype |= CGW_MOD_DATA;
break;
default:
return 4;
}
ptr++;
}
if (sscanf(++ptr, "%x.%hhx.%hhx.%128s", &can_id,
(unsigned char *)&modmsg->cf.flags,
(unsigned char *)&modmsg->cf.len, hexdata) != 4)
return 5;
modmsg->cf.can_id = can_id;
if (strlen(hexdata) != (CANFD_MAX_DLEN * 2))
return 6;
if (b64hex(hexdata, &modmsg->cf.data[0], CANFD_MAX_DLEN))
return 7;
return 0; /* ok */
}
int parse_rtlist(char *prgname, unsigned char *rxbuf, int len)
{
char ifname[IF_NAMESIZE]; /* internface name for if_indextoname() */
char ifname[IF_NAMESIZE]; /* interface name for if_indextoname() */
struct rtcanmsg *rtc;
struct rtattr *rta;
struct nlmsghdr *nlh;
@@ -419,6 +538,10 @@ int parse_rtlist(char *prgname, unsigned char *rxbuf, int len)
case CGW_MOD_OR:
case CGW_MOD_XOR:
case CGW_MOD_SET:
case CGW_FDMOD_AND:
case CGW_FDMOD_OR:
case CGW_FDMOD_XOR:
case CGW_FDMOD_SET:
case CGW_MOD_UID:
case CGW_LIM_HOPS:
case CGW_CS_XOR:
@@ -456,6 +579,9 @@ int parse_rtlist(char *prgname, unsigned char *rxbuf, int len)
printf("-s %s ", if_indextoname(src_ifindex, ifname));
printf("-d %s ", if_indextoname(dst_ifindex, ifname));
if (rtc->flags & CGW_FLAGS_CAN_FD)
printf("-X ");
if (rtc->flags & CGW_FLAGS_CAN_ECHO)
printf("-e ");
@@ -493,6 +619,22 @@ int parse_rtlist(char *prgname, unsigned char *rxbuf, int len)
printmod("SET", RTA_DATA(rta));
break;
case CGW_FDMOD_AND:
printfdmod("AND", RTA_DATA(rta));
break;
case CGW_FDMOD_OR:
printfdmod("OR", RTA_DATA(rta));
break;
case CGW_FDMOD_XOR:
printfdmod("XOR", RTA_DATA(rta));
break;
case CGW_FDMOD_SET:
printfdmod("SET", RTA_DATA(rta));
break;
case CGW_MOD_UID:
printf("-u %X ", *(__u32 *)RTA_DATA(rta));
break;
@@ -548,8 +690,7 @@ int main(int argc, char **argv)
struct {
struct nlmsghdr nh;
struct rtcanmsg rtcan;
char buf[600];
char buf[1500];
} req;
unsigned char rxbuf[8192]; /* netlink receive buffer */
@@ -565,19 +706,19 @@ int main(int argc, char **argv)
struct can_filter filter;
struct sockaddr_nl nladdr;
struct cgw_csum_xor cs_xor;
struct cgw_csum_crc8 cs_crc8;
struct cgw_csum_xor cs_xor = { 0 };
struct cgw_csum_crc8 cs_crc8 = { 0 };
char crc8tab[513] = {0};
struct modattr modmsg[CGW_MOD_FUNCS];
struct fdmodattr fdmodmsg[CGW_MOD_FUNCS];
int modidx = 0;
int fdmodidx = 0;
int i;
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:teiu:l:f:c:p:x:m:?")) != -1) {
while ((opt = getopt(argc, argv, "ADFLs:d:Xteiu:l:f:c:p:x:m:M:?")) != -1) {
switch (opt) {
case 'A':
@@ -608,6 +749,10 @@ int main(int argc, char **argv)
dst_ifindex = if_nametoindex(optarg);
break;
case 'X':
flags |= CGW_FLAGS_CAN_FD;
break;
case 't':
flags |= CGW_FLAGS_CAN_SRC_TSTAMP;
break;
@@ -625,7 +770,7 @@ int main(int argc, char **argv)
break;
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);
exit(1);
}
@@ -685,6 +830,14 @@ int main(int argc, char **argv)
}
break;
case 'M':
/* may be triggered by each of the CGW_FDMOD_FUNCS functions */
if ((fdmodidx < CGW_MOD_FUNCS) && (err = parse_fdmod(optarg, &fdmodmsg[fdmodidx++]))) {
printf("Problem %d with modification definition '%s'.\n", err, optarg);
exit(1);
}
break;
case '?':
print_usage(basename(argv[0]));
exit(0);
@@ -709,8 +862,20 @@ int main(int argc, char **argv)
exit(1);
}
if (!modidx && (have_cs_crc8 || have_cs_xor)) {
printf("-c or -x can only be used in conjunction with -m\n");
if (flags & CGW_FLAGS_CAN_FD) {
if (modidx) {
printf("No -m modifications allowed in CAN FD mode!\n");
exit(1);
}
} else {
if (fdmodidx) {
printf("No -M modifications allowed in Classic CAN mode!\n");
exit(1);
}
}
if ((!modidx && !fdmodidx) && (have_cs_crc8 || have_cs_xor)) {
printf("-c or -x can only be used in conjunction with -m/-M\n");
exit(1);
}
@@ -784,6 +949,10 @@ int main(int argc, char **argv)
for (i = 0; i < modidx; i++)
addattr_l(&req.nh, sizeof(req), modmsg[i].instruction, &modmsg[i], CGW_MODATTR_LEN);
/* add up to CGW_FDMOD_FUNCS modification definitions */
for (i = 0; i < fdmodidx; i++)
addattr_l(&req.nh, sizeof(req), fdmodmsg[i].instruction, &fdmodmsg[i], CGW_FDMODATTR_LEN);
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = 0;
+28 -23
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* canlogserver.c
*
@@ -41,28 +42,29 @@
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#include <libgen.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.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 <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/raw.h>
#include <linux/sockios.h>
#include <signal.h>
#include <errno.h>
#include "lib.h"
@@ -87,7 +89,8 @@ void print_usage(char *prg)
{
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\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, " -i <0|1> (invert the specified ID filter) *\n");
fprintf(stderr, " -e <emask> (mask for error frames)\n");
@@ -137,7 +140,7 @@ int idx2dindex(int ifidx, int socket)
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
perror("SIOCGIFNAME");
if (max_devname_len < strlen(ifr.ifr_name))
if (max_devname_len < (int)strlen(ifr.ifr_name))
max_devname_len = strlen(ifr.ifr_name);
strcpy(devname[i], ifr.ifr_name);
@@ -278,8 +281,12 @@ int main(int argc, char **argv)
inaddr.sin_port = htons(port);
while(bind(socki, (struct sockaddr*)&inaddr, sizeof(inaddr)) < 0) {
struct timespec f = {
.tv_nsec = 100 * 1000 * 1000,
};
printf(".");fflush(NULL);
usleep(100000);
nanosleep(&f, NULL);
}
if (listen(socki, 3) != 0) {
@@ -293,15 +300,14 @@ int main(int argc, char **argv)
//printf("accepted\n");
if (!fork())
break;
else
close(accsocket);
close(accsocket);
}
else if (errno != EINTR) {
perror("accept");
exit(1);
}
}
for (i=0; i<currmax; i++) {
#ifdef DEBUG
@@ -350,15 +356,14 @@ int main(int argc, char **argv)
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]);
if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX");
exit(1);
}
addr.can_ifindex = ifr.ifr_ifindex;
}
else
} else
addr.can_ifindex = 0; /* any can interface */
if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
@@ -407,7 +412,7 @@ int main(int argc, char **argv)
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]);
sprint_canframe(temp+strlen(temp), &frame, 0, maxdlen);
strcat(temp, "\n");
@@ -419,7 +424,7 @@ int main(int argc, char **argv)
#if 0
/* 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]);
fprint_canframe(stdout, &frame, "\n", 0, maxdlen);
#endif
+38 -35
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* canplayer.c - replay a compact CAN frame logfile to CAN devices
*
@@ -41,19 +42,19 @@
*
*/
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <libgen.h>
#include <stdlib.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/raw.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include "lib.h"
@@ -76,30 +77,32 @@ extern int optind, opterr, optopt;
void print_usage(char *prg)
{
fprintf(stderr, "%s - replay a compact CAN frame logfile to CAN devices.\n", prg);
fprintf(stderr, "\nUsage: %s <options> [interface assignment]*\n\n", prg);
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
fprintf(stderr, " -l <num> "
"(process input file <num> times)\n"
" "
"(Use 'i' for infinite loop - default: %d)\n", DEFAULT_LOOPS);
fprintf(stderr, " -t (ignore timestamps: "
"send frames immediately)\n");
fprintf(stderr, " -g <ms> (gap in milli "
"seconds - default: %d ms)\n", DEFAULT_GAP);
fprintf(stderr, " -s <s> (skip gaps in "
"timestamps > 's' seconds)\n");
fprintf(stderr, " -x (disable local "
"loopback of sent CAN frames)\n");
fprintf(stderr, " -v (verbose: print "
"sent CAN frames)\n\n");
fprintf(stderr, "Interface assignment: 0..n assignments like "
"<write-if>=<log-if>\n");
fprintf(stderr, "e.g. vcan2=can0 ( send frames received from can0 on "
"vcan2 )\n");
fprintf(stderr, "extra hook: stdout=can0 ( print logfile line marked with can0 on "
"stdout )\n");
fprintf(stderr, "No assignments => send frames to the interface(s) they "
"had been received from.\n\n");
fprintf(stderr, "Options:\n");
fprintf(stderr, " -I <infile> (default stdin)\n");
fprintf(stderr, " -l <num> "
"(process input file <num> times)\n"
" "
"(Use 'i' for infinite loop - default: %d)\n", DEFAULT_LOOPS);
fprintf(stderr, " -t (ignore timestamps: "
"send frames immediately)\n");
fprintf(stderr, " -g <ms> (gap in milli "
"seconds - default: %d ms)\n", DEFAULT_GAP);
fprintf(stderr, " -s <s> (skip gaps in "
"timestamps > 's' seconds)\n");
fprintf(stderr, " -x (disable local "
"loopback of sent CAN frames)\n");
fprintf(stderr, " -v (verbose: print "
"sent CAN frames)\n\n");
fprintf(stderr, "Interface assignment:\n");
fprintf(stderr, " 0..n assignments like <write-if>=<log-if>\n\n");
fprintf(stderr, " e.g. vcan2=can0 (send frames received from can0 on "
"vcan2)\n");
fprintf(stderr, " extra hook: stdout=can0 (print logfile line marked with can0 on "
"stdout)\n");
fprintf(stderr, " No assignments => send frames to the interface(s) they "
"had been received from\n\n");
fprintf(stderr, "Lines in the logfile not beginning with '(' (start of "
"timestamp) are ignored.\n\n");
}
@@ -212,7 +215,7 @@ int add_assignment(char *mode, int socket, char *txname, char *rxname,
}
strcpy(asgn[i].rxif, rxname);
if (strcmp(txname, "stdout")) {
if (strcmp(txname, "stdout") != 0) {
strcpy(ifr.ifr_name, txname);
if (ioctl(socket, SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX");
@@ -348,7 +351,7 @@ int main(int argc, char **argv)
}
if (assignments) {
/* add & check user assginments from commandline */
/* add & check user assignments from commandline */
for (i=0; i<assignments; i++) {
if (strlen(argv[optind+i]) >= BUFSZ) {
fprintf(stderr, "Assignment too long!\n");
@@ -356,7 +359,7 @@ int main(int argc, char **argv)
return 1;
}
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] == '=')
break;
}
@@ -392,7 +395,7 @@ int main(int argc, char **argv)
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) {
fprintf(stderr, "incorrect line format in logfile\n");
return 1;
@@ -471,7 +474,7 @@ int main(int argc, char **argv)
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) {
fprintf(stderr, "incorrect line format in logfile\n");
return 1;
@@ -492,7 +495,7 @@ int main(int argc, char **argv)
/* test for logfile timestamps jumping backwards OR */
/* if the user likes to skip long gaps in the timestamps */
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);
last_log_tv = log_tv;
+30 -14
View File
@@ -1,5 +1,6 @@
/* 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
* All rights reserved.
@@ -55,6 +56,29 @@
#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 s; /* can raw socket */
@@ -67,24 +91,15 @@ int main(int argc, char **argv)
/* check command line options */
if (argc != 3) {
fprintf(stderr, "Usage: %s <device> <can_frame>.\n", argv[0]);
print_usage(argv[0]);
return 1;
}
/* parse CAN frame */
required_mtu = parse_canframe(argv[2], &frame);
if (!required_mtu){
fprintf(stderr, "\nWrong CAN-frame format! Try:\n\n");
fprintf(stderr, " <can_id>#{R|data} for CAN 2.0 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, "<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##311\n 1F334455#1122334455667788 / 123#R ");
fprintf(stderr, "for remote transmission request.\n\n");
fprintf(stderr, "\nWrong CAN-frame format!\n\n");
print_usage(argv[0]);
return 1;
}
@@ -102,10 +117,11 @@ int main(int argc, char **argv)
return 1;
}
memset(&addr, 0, sizeof(addr));
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
if (required_mtu > CAN_MTU) {
if (required_mtu > (int)CAN_MTU) {
/* check if the frame fits into the CAN netdevice */
if (ioctl(s, SIOCGIFMTU, &ifr) < 0) {
+367
View File
@@ -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);
}
+393 -297
View File
File diff suppressed because it is too large Load Diff
+19
View File
@@ -0,0 +1,19 @@
if(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: ${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt")
endif()
file(READ "${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt" files)
string(REGEX REPLACE "[\r\n]" ";" files "${files}")
foreach(file ${files})
message(STATUS "Uninstalling ${file}")
if(EXISTS "${file}")
file(REMOVE ${file})
if (EXISTS "${file}")
message(FATAL_ERROR "Problem when removing ${file}, please check your permissions")
endif()
else()
message(STATUS "File ${file} does not exist.")
endif()
endforeach()
+3
View File
@@ -88,6 +88,9 @@ AC_CHECK_DECL(AF_CAN,,
AC_CHECK_DECL(N_SLCAN,,
[AC_DEFINE([N_SLCAN], [17], [N_SLCAN])]
)
AC_CHECK_DECL(SCM_TIMESTAMPING_OPT_STATS,,
[AC_DEFINE([SCM_TIMESTAMPING_OPT_STATS], [54], [SCM_TIMESTAMPING_OPT_STATS])]
)
AC_DEFINE(_GNU_SOURCE)
+3 -6
View File
@@ -1,4 +1,4 @@
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/* SPDX-License-Identifier: ((GPL-2.0-only WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* linux/can.h
*
@@ -77,7 +77,7 @@ typedef __u32 canid_t;
/*
* Controller Area Network Error Message Frame Mask structure
*
* bit 0-28 : error class mask (see include/linux/can/error.h)
* bit 0-28 : error class mask (see include/uapi/linux/can/error.h)
* bit 29-31 : set to zero
*/
typedef __u32 can_err_mask_t;
@@ -181,10 +181,7 @@ struct sockaddr_can {
int can_ifindex;
union {
/* transport protocol class address information (e.g. ISOTP) */
struct {
canid_t rx_id;
canid_t tx_id;
} tp;
struct { canid_t rx_id, tx_id; } tp;
/* J1939 address information */
struct {
+1 -1
View File
@@ -1,4 +1,4 @@
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/* SPDX-License-Identifier: ((GPL-2.0-only WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* linux/can/bcm.h
*
+1 -1
View File
@@ -1,4 +1,4 @@
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/* SPDX-License-Identifier: ((GPL-2.0-only WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* linux/can/error.h
*
+16 -3
View File
@@ -1,4 +1,4 @@
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/* SPDX-License-Identifier: ((GPL-2.0-only WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* linux/can/gw.h
*
@@ -80,6 +80,10 @@ enum {
CGW_DELETED, /* number of deleted CAN frames (see max_hops param) */
CGW_LIM_HOPS, /* limit the number of hops of this specific rule */
CGW_MOD_UID, /* user defined identifier for modification updates */
CGW_FDMOD_AND, /* CAN FD frame modification binary AND */
CGW_FDMOD_OR, /* CAN FD frame modification binary OR */
CGW_FDMOD_XOR, /* CAN FD frame modification binary XOR */
CGW_FDMOD_SET, /* CAN FD frame modification set alternate values */
__CGW_MAX
};
@@ -88,15 +92,18 @@ enum {
#define CGW_FLAGS_CAN_ECHO 0x01
#define CGW_FLAGS_CAN_SRC_TSTAMP 0x02
#define CGW_FLAGS_CAN_IIF_TX_OK 0x04
#define CGW_FLAGS_CAN_FD 0x08
#define CGW_MOD_FUNCS 4 /* AND OR XOR SET */
/* CAN frame elements that are affected by curr. 3 CAN frame modifications */
#define CGW_MOD_ID 0x01
#define CGW_MOD_DLC 0x02
#define CGW_MOD_DLC 0x02 /* contains the data length in bytes */
#define CGW_MOD_LEN CGW_MOD_DLC /* CAN FD length representation */
#define CGW_MOD_DATA 0x04
#define CGW_MOD_FLAGS 0x08 /* CAN FD flags */
#define CGW_FRAME_MODS 3 /* ID DLC DATA */
#define CGW_FRAME_MODS 4 /* ID DLC/LEN DATA FLAGS */
#define MAX_MODFUNCTIONS (CGW_MOD_FUNCS * CGW_FRAME_MODS)
@@ -105,7 +112,13 @@ struct cgw_frame_mod {
__u8 modtype;
} __attribute__((packed));
struct cgw_fdframe_mod {
struct canfd_frame cf;
__u8 modtype;
} __attribute__((packed));
#define CGW_MODATTR_LEN sizeof(struct cgw_frame_mod)
#define CGW_FDMODATTR_LEN sizeof(struct cgw_fdframe_mod)
struct cgw_csum_xor {
__s8 from_idx;
+8 -10
View File
@@ -1,10 +1,10 @@
/* SPDX-License-Identifier: ((GPL-2.0-only WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* 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) 2008 Volkswagen Group Electronic Research
* Copyright (c) 2020 Volkswagen Group Electronic Research
* All rights reserved.
*
* 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
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* Send feedback to <linux-can@vger.kernel.org>
*/
#ifndef CAN_ISOTP_H
#define CAN_ISOTP_H
#ifndef _UAPI_CAN_ISOTP_H
#define _UAPI_CAN_ISOTP_H
#include <linux/types.h>
#include <linux/can.h>
#define SOL_CAN_ISOTP (SOL_CAN_BASE + CAN_ISOTP)
@@ -123,7 +122,6 @@ struct can_isotp_ll_options {
/* by the CAN netdriver configuration */
};
/* flags for isotp behaviour */
#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_RXSTMIN 0x100 /* ignore CFs depending on rx stmin */
#define CAN_ISOTP_RX_EXT_ADDR 0x200 /* different rx extended addressing */
#define CAN_ISOTP_WAIT_TX_DONE 0x400 /* wait for tx completion */
/* default values */
@@ -161,7 +160,6 @@ struct can_isotp_ll_options {
* these default settings can be changed via sockopts.
* For that reason the STmin value is intentionally _not_ checked for
* consistency and copied directly into the flow control (FC) frame.
*
*/
#endif
#endif /* !_UAPI_CAN_ISOTP_H */
+24 -7
View File
@@ -1,4 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/*
* j1939.h
*
@@ -16,9 +16,15 @@
#include <linux/socket.h>
#include <linux/can.h>
#define J1939_IDLE_ADDR 0xfe
#define J1939_NO_ADDR 0xff
#define J1939_MAX_UNICAST_ADDR 0xfd
#define J1939_IDLE_ADDR 0xfe
#define J1939_NO_ADDR 0xff /* == broadcast or no addr */
#define J1939_NO_NAME 0
#define J1939_PGN_REQUEST 0x0ea00 /* Request PG */
#define J1939_PGN_ADDRESS_CLAIMED 0x0ee00 /* Address Claimed */
#define J1939_PGN_ADDRESS_COMMANDED 0x0fed8 /* Commanded Address */
#define J1939_PGN_PDU1_MAX 0x3ff00
#define J1939_PGN_MAX 0x3ffff
#define J1939_NO_PGN 0x40000
/* J1939 Parameter Group Number
@@ -58,23 +64,34 @@ typedef __u64 name_t;
enum {
SO_J1939_FILTER = 1, /* set filters */
SO_J1939_PROMISC = 2, /* set/clr promiscuous mode */
SO_J1939_RECV_OWN = 3,
SO_J1939_SEND_PRIO = 4,
SO_J1939_SEND_PRIO = 3,
SO_J1939_ERRQUEUE = 4,
};
enum {
SCM_J1939_DEST_ADDR = 1,
SCM_J1939_DEST_NAME = 2,
SCM_J1939_PRIO = 3,
SCM_J1939_ERRQUEUE = 4,
};
enum {
J1939_NLA_PAD,
J1939_NLA_BYTES_ACKED,
};
enum {
J1939_EE_INFO_NONE,
J1939_EE_INFO_TX_ABORT,
};
struct j1939_filter {
name_t name;
name_t name_mask;
__u8 addr;
__u8 addr_mask;
pgn_t pgn;
pgn_t pgn_mask;
__u8 addr;
__u8 addr_mask;
};
#define J1939_FILTER_MAX 512 /* maximum number of j1939_filter set via setsockopt() */
+4 -4
View File
@@ -1,4 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/*
* linux/can/netlink.h
*
@@ -40,15 +40,15 @@ struct can_bittiming {
};
/*
* CAN harware-dependent bit-timing constant
* CAN hardware-dependent bit-timing constant
*
* Used for calculating and checking bit-timing parameters
*/
struct can_bittiming_const {
char name[16]; /* Name of the CAN controller hardware */
__u32 tseg1_min; /* Time segement 1 = prop_seg + phase_seg1 */
__u32 tseg1_min; /* Time segment 1 = prop_seg + phase_seg1 */
__u32 tseg1_max;
__u32 tseg2_min; /* Time segement 2 = phase_seg2 */
__u32 tseg2_min; /* Time segment 2 = phase_seg2 */
__u32 tseg2_max;
__u32 sjw_max; /* Synchronisation jump width */
__u32 brp_min; /* Bit-rate prescaler */
+4 -1
View File
@@ -1,4 +1,4 @@
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
/* SPDX-License-Identifier: ((GPL-2.0-only WITH Linux-syscall-note) OR BSD-3-Clause) */
/*
* linux/can/raw.h
*
@@ -49,6 +49,9 @@
#include <linux/can.h>
#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) */
+1 -1
View File
@@ -1,4 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
#ifndef _UAPI_CAN_VXCAN_H
#define _UAPI_CAN_VXCAN_H
+54
View File
@@ -0,0 +1,54 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _UAPI_LINUX_ERRQUEUE_H
#define _UAPI_LINUX_ERRQUEUE_H
#include <linux/types.h>
struct sock_extended_err {
__u32 ee_errno;
__u8 ee_origin;
__u8 ee_type;
__u8 ee_code;
__u8 ee_pad;
__u32 ee_info;
__u32 ee_data;
};
#define SO_EE_ORIGIN_NONE 0
#define SO_EE_ORIGIN_LOCAL 1
#define SO_EE_ORIGIN_ICMP 2
#define SO_EE_ORIGIN_ICMP6 3
#define SO_EE_ORIGIN_TXSTATUS 4
#define SO_EE_ORIGIN_ZEROCOPY 5
#define SO_EE_ORIGIN_TXTIME 6
#define SO_EE_ORIGIN_TIMESTAMPING SO_EE_ORIGIN_TXSTATUS
#define SO_EE_OFFENDER(ee) ((struct sockaddr*)((ee)+1))
#define SO_EE_CODE_ZEROCOPY_COPIED 1
#define SO_EE_CODE_TXTIME_INVALID_PARAM 1
#define SO_EE_CODE_TXTIME_MISSED 2
/**
* struct scm_timestamping - timestamps exposed through cmsg
*
* The timestamping interfaces SO_TIMESTAMPING, MSG_TSTAMP_*
* communicate network timestamps by passing this struct in a cmsg with
* recvmsg(). See Documentation/networking/timestamping.txt for details.
*/
struct scm_timestamping {
struct timespec ts[3];
};
/* The type of scm_timestamping, passed in sock_extended_err ee_info.
* This defines the type of ts[0]. For SCM_TSTAMP_SND only, if ts[0]
* is zero, then this is a hardware timestamp and recorded in ts[2].
*/
enum {
SCM_TSTAMP_SND, /* driver passed skb to NIC, or HW */
SCM_TSTAMP_SCHED, /* data entered the packet scheduler */
SCM_TSTAMP_ACK, /* data acknowledged by peer */
};
#endif /* _UAPI_LINUX_ERRQUEUE_H */
+162
View File
@@ -0,0 +1,162 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
* Userspace API for hardware time stamping of network packets
*
* Copyright (C) 2008,2009 Intel Corporation
* Author: Patrick Ohly <patrick.ohly@intel.com>
*
*/
#ifndef _NET_TIMESTAMPING_H
#define _NET_TIMESTAMPING_H
#include <linux/types.h>
#include <linux/socket.h> /* for SO_TIMESTAMPING */
/* SO_TIMESTAMPING gets an integer bit field comprised of these values */
enum {
SOF_TIMESTAMPING_TX_HARDWARE = (1<<0),
SOF_TIMESTAMPING_TX_SOFTWARE = (1<<1),
SOF_TIMESTAMPING_RX_HARDWARE = (1<<2),
SOF_TIMESTAMPING_RX_SOFTWARE = (1<<3),
SOF_TIMESTAMPING_SOFTWARE = (1<<4),
SOF_TIMESTAMPING_SYS_HARDWARE = (1<<5),
SOF_TIMESTAMPING_RAW_HARDWARE = (1<<6),
SOF_TIMESTAMPING_OPT_ID = (1<<7),
SOF_TIMESTAMPING_TX_SCHED = (1<<8),
SOF_TIMESTAMPING_TX_ACK = (1<<9),
SOF_TIMESTAMPING_OPT_CMSG = (1<<10),
SOF_TIMESTAMPING_OPT_TSONLY = (1<<11),
SOF_TIMESTAMPING_OPT_STATS = (1<<12),
SOF_TIMESTAMPING_OPT_PKTINFO = (1<<13),
SOF_TIMESTAMPING_OPT_TX_SWHW = (1<<14),
SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_TX_SWHW,
SOF_TIMESTAMPING_MASK = (SOF_TIMESTAMPING_LAST - 1) |
SOF_TIMESTAMPING_LAST
};
/*
* SO_TIMESTAMPING flags are either for recording a packet timestamp or for
* reporting the timestamp to user space.
* Recording flags can be set both via socket options and control messages.
*/
#define SOF_TIMESTAMPING_TX_RECORD_MASK (SOF_TIMESTAMPING_TX_HARDWARE | \
SOF_TIMESTAMPING_TX_SOFTWARE | \
SOF_TIMESTAMPING_TX_SCHED | \
SOF_TIMESTAMPING_TX_ACK)
/**
* struct hwtstamp_config - %SIOCGHWTSTAMP and %SIOCSHWTSTAMP parameter
*
* @flags: no flags defined right now, must be zero for %SIOCSHWTSTAMP
* @tx_type: one of HWTSTAMP_TX_*
* @rx_filter: one of HWTSTAMP_FILTER_*
*
* %SIOCGHWTSTAMP and %SIOCSHWTSTAMP expect a &struct ifreq with a
* ifr_data pointer to this structure. For %SIOCSHWTSTAMP, if the
* driver or hardware does not support the requested @rx_filter value,
* the driver may use a more general filter mode. In this case
* @rx_filter will indicate the actual mode on return.
*/
struct hwtstamp_config {
int flags;
int tx_type;
int rx_filter;
};
/* possible values for hwtstamp_config->tx_type */
enum hwtstamp_tx_types {
/*
* No outgoing packet will need hardware time stamping;
* should a packet arrive which asks for it, no hardware
* time stamping will be done.
*/
HWTSTAMP_TX_OFF,
/*
* Enables hardware time stamping for outgoing packets;
* the sender of the packet decides which are to be
* time stamped by setting %SOF_TIMESTAMPING_TX_SOFTWARE
* before sending the packet.
*/
HWTSTAMP_TX_ON,
/*
* Enables time stamping for outgoing packets just as
* HWTSTAMP_TX_ON does, but also enables time stamp insertion
* directly into Sync packets. In this case, transmitted Sync
* packets will not received a time stamp via the socket error
* queue.
*/
HWTSTAMP_TX_ONESTEP_SYNC,
};
/* possible values for hwtstamp_config->rx_filter */
enum hwtstamp_rx_filters {
/* time stamp no incoming packet at all */
HWTSTAMP_FILTER_NONE,
/* time stamp any incoming packet */
HWTSTAMP_FILTER_ALL,
/* return value: time stamp all packets requested plus some others */
HWTSTAMP_FILTER_SOME,
/* PTP v1, UDP, any kind of event packet */
HWTSTAMP_FILTER_PTP_V1_L4_EVENT,
/* PTP v1, UDP, Sync packet */
HWTSTAMP_FILTER_PTP_V1_L4_SYNC,
/* PTP v1, UDP, Delay_req packet */
HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ,
/* PTP v2, UDP, any kind of event packet */
HWTSTAMP_FILTER_PTP_V2_L4_EVENT,
/* PTP v2, UDP, Sync packet */
HWTSTAMP_FILTER_PTP_V2_L4_SYNC,
/* PTP v2, UDP, Delay_req packet */
HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ,
/* 802.AS1, Ethernet, any kind of event packet */
HWTSTAMP_FILTER_PTP_V2_L2_EVENT,
/* 802.AS1, Ethernet, Sync packet */
HWTSTAMP_FILTER_PTP_V2_L2_SYNC,
/* 802.AS1, Ethernet, Delay_req packet */
HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ,
/* PTP v2/802.AS1, any layer, any kind of event packet */
HWTSTAMP_FILTER_PTP_V2_EVENT,
/* PTP v2/802.AS1, any layer, Sync packet */
HWTSTAMP_FILTER_PTP_V2_SYNC,
/* PTP v2/802.AS1, any layer, Delay_req packet */
HWTSTAMP_FILTER_PTP_V2_DELAY_REQ,
/* NTP, UDP, all versions and packet modes */
HWTSTAMP_FILTER_NTP_ALL,
};
/* SCM_TIMESTAMPING_PKTINFO control message */
struct scm_ts_pktinfo {
__u32 if_index;
__u32 pkt_length;
__u32 reserved[2];
};
/*
* SO_TXTIME gets a struct sock_txtime with flags being an integer bit
* field comprised of these values.
*/
enum txtime_flags {
SOF_TXTIME_DEADLINE_MODE = (1 << 0),
SOF_TXTIME_REPORT_ERRORS = (1 << 1),
SOF_TXTIME_FLAGS_LAST = SOF_TXTIME_REPORT_ERRORS,
SOF_TXTIME_FLAGS_MASK = (SOF_TXTIME_FLAGS_LAST - 1) |
SOF_TXTIME_FLAGS_LAST
};
struct sock_txtime {
__kernel_clockid_t clockid;/* reference clockid */
__u32 flags; /* as defined by enum txtime_flags */
};
#endif /* _NET_TIMESTAMPING_H */
+252
View File
@@ -0,0 +1,252 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _UAPI__LINUX_NETLINK_H
#define _UAPI__LINUX_NETLINK_H
#include <linux/kernel.h>
#include <linux/socket.h> /* for __kernel_sa_family_t */
#include <linux/types.h>
#define NETLINK_ROUTE 0 /* Routing/device hook */
#define NETLINK_UNUSED 1 /* Unused number */
#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */
#define NETLINK_FIREWALL 3 /* Unused number, formerly ip_queue */
#define NETLINK_SOCK_DIAG 4 /* socket monitoring */
#define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */
#define NETLINK_XFRM 6 /* ipsec */
#define NETLINK_SELINUX 7 /* SELinux event notifications */
#define NETLINK_ISCSI 8 /* Open-iSCSI */
#define NETLINK_AUDIT 9 /* auditing */
#define NETLINK_FIB_LOOKUP 10
#define NETLINK_CONNECTOR 11
#define NETLINK_NETFILTER 12 /* netfilter subsystem */
#define NETLINK_IP6_FW 13
#define NETLINK_DNRTMSG 14 /* DECnet routing messages */
#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */
#define NETLINK_GENERIC 16
/* leave room for NETLINK_DM (DM Events) */
#define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */
#define NETLINK_ECRYPTFS 19
#define NETLINK_RDMA 20
#define NETLINK_CRYPTO 21 /* Crypto layer */
#define NETLINK_SMC 22 /* SMC monitoring */
#define NETLINK_INET_DIAG NETLINK_SOCK_DIAG
#define MAX_LINKS 32
struct sockaddr_nl {
__kernel_sa_family_t nl_family; /* AF_NETLINK */
unsigned short nl_pad; /* zero */
__u32 nl_pid; /* port ID */
__u32 nl_groups; /* multicast groups mask */
};
struct nlmsghdr {
__u32 nlmsg_len; /* Length of message including header */
__u16 nlmsg_type; /* Message content */
__u16 nlmsg_flags; /* Additional flags */
__u32 nlmsg_seq; /* Sequence number */
__u32 nlmsg_pid; /* Sending process port ID */
};
/* Flags values */
#define NLM_F_REQUEST 0x01 /* It is request message. */
#define NLM_F_MULTI 0x02 /* Multipart message, terminated by NLMSG_DONE */
#define NLM_F_ACK 0x04 /* Reply with ack, with zero or error code */
#define NLM_F_ECHO 0x08 /* Echo this request */
#define NLM_F_DUMP_INTR 0x10 /* Dump was inconsistent due to sequence change */
#define NLM_F_DUMP_FILTERED 0x20 /* Dump was filtered as requested */
/* Modifiers to GET request */
#define NLM_F_ROOT 0x100 /* specify tree root */
#define NLM_F_MATCH 0x200 /* return all matching */
#define NLM_F_ATOMIC 0x400 /* atomic GET */
#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH)
/* Modifiers to NEW request */
#define NLM_F_REPLACE 0x100 /* Override existing */
#define NLM_F_EXCL 0x200 /* Do not touch, if it exists */
#define NLM_F_CREATE 0x400 /* Create, if it does not exist */
#define NLM_F_APPEND 0x800 /* Add to end of list */
/* Modifiers to DELETE request */
#define NLM_F_NONREC 0x100 /* Do not delete recursively */
/* Flags for ACK message */
#define NLM_F_CAPPED 0x100 /* request was capped */
#define NLM_F_ACK_TLVS 0x200 /* extended ACK TVLs were included */
/*
4.4BSD ADD NLM_F_CREATE|NLM_F_EXCL
4.4BSD CHANGE NLM_F_REPLACE
True CHANGE NLM_F_CREATE|NLM_F_REPLACE
Append NLM_F_CREATE
Check NLM_F_EXCL
*/
#define NLMSG_ALIGNTO 4U
#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
#define NLMSG_LENGTH(len) ((len) + NLMSG_HDRLEN)
#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
#define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
(struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \
(nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
(int)((nlh)->nlmsg_len) <= (len))
#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
#define NLMSG_NOOP 0x1 /* Nothing. */
#define NLMSG_ERROR 0x2 /* Error */
#define NLMSG_DONE 0x3 /* End of a dump */
#define NLMSG_OVERRUN 0x4 /* Data lost */
#define NLMSG_MIN_TYPE 0x10 /* < 0x10: reserved control messages */
struct nlmsgerr {
int error;
struct nlmsghdr msg;
/*
* followed by the message contents unless NETLINK_CAP_ACK was set
* or the ACK indicates success (error == 0)
* message length is aligned with NLMSG_ALIGN()
*/
/*
* followed by TLVs defined in enum nlmsgerr_attrs
* if NETLINK_EXT_ACK was set
*/
};
/**
* enum nlmsgerr_attrs - nlmsgerr attributes
* @NLMSGERR_ATTR_UNUSED: unused
* @NLMSGERR_ATTR_MSG: error message string (string)
* @NLMSGERR_ATTR_OFFS: offset of the invalid attribute in the original
* message, counting from the beginning of the header (u32)
* @NLMSGERR_ATTR_COOKIE: arbitrary subsystem specific cookie to
* be used - in the success case - to identify a created
* object or operation or similar (binary)
* @__NLMSGERR_ATTR_MAX: number of attributes
* @NLMSGERR_ATTR_MAX: highest attribute number
*/
enum nlmsgerr_attrs {
NLMSGERR_ATTR_UNUSED,
NLMSGERR_ATTR_MSG,
NLMSGERR_ATTR_OFFS,
NLMSGERR_ATTR_COOKIE,
__NLMSGERR_ATTR_MAX,
NLMSGERR_ATTR_MAX = __NLMSGERR_ATTR_MAX - 1
};
#define NETLINK_ADD_MEMBERSHIP 1
#define NETLINK_DROP_MEMBERSHIP 2
#define NETLINK_PKTINFO 3
#define NETLINK_BROADCAST_ERROR 4
#define NETLINK_NO_ENOBUFS 5
#ifndef __KERNEL__
#define NETLINK_RX_RING 6
#define NETLINK_TX_RING 7
#endif
#define NETLINK_LISTEN_ALL_NSID 8
#define NETLINK_LIST_MEMBERSHIPS 9
#define NETLINK_CAP_ACK 10
#define NETLINK_EXT_ACK 11
#define NETLINK_GET_STRICT_CHK 12
struct nl_pktinfo {
__u32 group;
};
struct nl_mmap_req {
unsigned int nm_block_size;
unsigned int nm_block_nr;
unsigned int nm_frame_size;
unsigned int nm_frame_nr;
};
struct nl_mmap_hdr {
unsigned int nm_status;
unsigned int nm_len;
__u32 nm_group;
/* credentials */
__u32 nm_pid;
__u32 nm_uid;
__u32 nm_gid;
};
#ifndef __KERNEL__
enum nl_mmap_status {
NL_MMAP_STATUS_UNUSED,
NL_MMAP_STATUS_RESERVED,
NL_MMAP_STATUS_VALID,
NL_MMAP_STATUS_COPY,
NL_MMAP_STATUS_SKIP,
};
#define NL_MMAP_MSG_ALIGNMENT NLMSG_ALIGNTO
#define NL_MMAP_MSG_ALIGN(sz) __ALIGN_KERNEL(sz, NL_MMAP_MSG_ALIGNMENT)
#define NL_MMAP_HDRLEN NL_MMAP_MSG_ALIGN(sizeof(struct nl_mmap_hdr))
#endif
#define NET_MAJOR 36 /* Major 36 is reserved for networking */
enum {
NETLINK_UNCONNECTED = 0,
NETLINK_CONNECTED,
};
/*
* <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)-->
* +---------------------+- - -+- - - - - - - - - -+- - -+
* | Header | Pad | Payload | Pad |
* | (struct nlattr) | ing | | ing |
* +---------------------+- - -+- - - - - - - - - -+- - -+
* <-------------- nlattr->nla_len -------------->
*/
struct nlattr {
__u16 nla_len;
__u16 nla_type;
};
/*
* nla_type (16 bits)
* +---+---+-------------------------------+
* | N | O | Attribute Type |
* +---+---+-------------------------------+
* N := Carries nested attributes
* O := Payload stored in network byte order
*
* Note: The N and O flag are mutually exclusive.
*/
#define NLA_F_NESTED (1 << 15)
#define NLA_F_NET_BYTEORDER (1 << 14)
#define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER)
#define NLA_ALIGNTO 4
#define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1))
#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr)))
/* Generic 32 bitflags attribute content sent to the kernel.
*
* The value is a bitmap that defines the values being set
* The selector is a bitmask that defines which value is legit
*
* Examples:
* value = 0x0, and selector = 0x1
* implies we are selecting bit 1 and we want to set its value to 0.
*
* value = 0x2, and selector = 0x2
* implies we are selecting bit 2 and we want to set its value to 1.
*
*/
struct nla_bitfield32 {
__u32 value;
__u32 selector;
};
#endif /* _UAPI__LINUX_NETLINK_H */
+195 -61
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* isotpdump.c - dump and explain ISO15765-2 protocol CAN frames
*
@@ -41,20 +42,23 @@
*
*/
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <libgen.h>
#include <strings.h>
#include <time.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <linux/sockios.h>
#include "terminal.h"
#define NO_CAN_ID 0xFFFFFFFFU
@@ -65,17 +69,130 @@ const int canfd_on = 1;
void print_usage(char *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, " -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 (rx addr). Use 'any' for all)\n");
fprintf(stderr, " -c (color mode)\n");
fprintf(stderr, " -a (print data also in ASCII-chars)\n");
fprintf(stderr, " -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\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, " -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, " -c (color mode)\n");
fprintf(stderr, " -a (print data also in ASCII-chars)\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, "\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 \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, " [NRC] = Negative Response Code\n");
fprintf(stderr, " [???] = Unknown (not specified)\n");
fprintf(stderr, "\n");
}
void print_uds_message(int service, int nrc)
{
char *service_name;
char *flag = "[???]";
if ((service >= 0x50 && service <= 0x7E) || (service >= 0xC3 && service <= 0xC8)) {
flag = "[PSR]";
service = service - 0x40;
} else if ((service >= 0x10 && service <= 0x3E) ||
(service >= 0x83 && service <= 0x88) ||
(service >= 0xBA && service <= 0xBE))
flag = "[SRQ]";
switch(service) {
case 0x10: service_name = "DiagnosticSessionControl"; break;
case 0x11: service_name = "ECUReset"; break;
case 0x14: service_name = "ClearDiagnosticInformation"; break;
case 0x19: service_name = "ReadDTCInformation"; break;
case 0x22: service_name = "ReadDataByIdentifier"; break;
case 0x23: service_name = "ReadMemoryByAddress"; break;
case 0x24: service_name = "ReadScalingDataByIdentifier"; break;
case 0x27: service_name = "SecurityAccess"; break;
case 0x28: service_name = "CommunicationControl"; break;
case 0x2A: service_name = "ReadDataByPeriodicIdentifier"; break;
case 0x2C: service_name = "DynamicallyDefineDataIdentifier"; break;
case 0x2E: service_name = "WriteDataByIdentifier"; break;
case 0x2F: service_name = "InputOutputControlByIdentifier"; break;
case 0x31: service_name = "RoutineControl"; break;
case 0x34: service_name = "RequestDownload"; break;
case 0x35: service_name = "RequestUpload"; break;
case 0x36: service_name = "TransferData"; break;
case 0x37: service_name = "RequestTransferExit"; break;
case 0x38: service_name = "RequestFileTransfer"; break;
case 0x3D: service_name = "WriteMemoryByAddress"; break;
case 0x3E: service_name = "TesterPresent"; break;
case 0x83: service_name = "AccessTimingParameter"; break;
case 0x84: service_name = "SecuredDataTransmision"; break;
case 0x85: service_name = "ControlDTCSetting"; break;
case 0x86: service_name = "ResponseOnEvent"; break;
case 0x87: service_name = "LinkControl"; break;
case 0x7F: flag = "[NRC]";
switch (nrc) {
case 0x00: service_name = "positiveResponse"; break;
case 0x10: service_name = "generalReject"; break;
case 0x11: service_name = "serviceNotSupported"; break;
case 0x12: service_name = "sub-functionNotSupported"; break;
case 0x13: service_name = "incorrectMessageLengthOrInvalidFormat"; break;
case 0x14: service_name = "responseTooLong"; break;
case 0x21: service_name = "busyRepeatRequest"; break;
case 0x22: service_name = "conditionsNotCorrect"; break;
case 0x24: service_name = "requestSequenceError"; break;
case 0x25: service_name = "noResponseFromSubnetComponent"; break;
case 0x26: service_name = "FailurePreventsExecutionOfRequestedAction"; break;
case 0x31: service_name = "requestOutOfRange"; break;
case 0x33: service_name = "securityAccessDenied"; break;
case 0x35: service_name = "invalidKey"; break;
case 0x36: service_name = "exceedNumberOfAttempts"; break;
case 0x37: service_name = "requiredTimeDelayNotExpired"; break;
case 0x70: service_name = "uploadDownloadNotAccepted"; break;
case 0x71: service_name = "transferDataSuspended"; break;
case 0x72: service_name = "generalProgrammingFailure"; break;
case 0x73: service_name = "wrongBlockSequenceCounter"; break;
case 0x78: service_name = "requestCorrectlyReceived-ResponsePending"; break;
case 0x7E: service_name = "sub-functionNotSupportedInActiveSession"; break;
case 0x7F: service_name = "serviceNotSupportedInActiveSession"; break;
case 0x81: service_name = "rpmTooHigh"; break;
case 0x82: service_name = "rpmTooLow"; break;
case 0x83: service_name = "engineIsRunning"; break;
case 0x84: service_name = "engineIsNotRunning"; break;
case 0x85: service_name = "engineRunTimeTooLow"; break;
case 0x86: service_name = "temperatureTooHigh"; break;
case 0x87: service_name = "temperatureTooLow"; break;
case 0x88: service_name = "vehicleSpeedTooHigh"; break;
case 0x89: service_name = "vehicleSpeedTooLow"; break;
case 0x8A: service_name = "throttle/PedalTooHigh"; break;
case 0x8B: service_name = "throttle/PedalTooLow"; break;
case 0x8C: service_name = "transmissionRangeNotInNeutral"; break;
case 0x8D: service_name = "transmissionRangeNotInGear"; break;
case 0x8F: service_name = "brakeSwitch(es)NotClosed (Brake Pedal not pressed or not applied)"; break;
case 0x90: service_name = "shifterLeverNotInPark"; break;
case 0x91: service_name = "torqueConverterClutchLocked"; break;
case 0x92: service_name = "voltageTooHigh"; break;
case 0x93: service_name = "voltageTooLow"; break;
default:
if (nrc > 0x37 && nrc < 0x50) {
service_name = "reservedByExtendedDataLinkSecurityDocument"; break;
}
else if (nrc > 0x93 && nrc < 0xF0) {
service_name = "reservedForSpecificConditionsNotCorrect"; break;
}
else if (nrc > 0xEF && nrc < 0xFE) {
service_name = "vehicleManufacturerSpecificConditionsNotCorrect"; break;
}
else {
service_name = "ISOSAEReserved"; break;
}
}
break;
default: service_name = "Unknown";
}
printf("%s %s", flag, service_name);
}
int main(int argc, char **argv)
{
int s;
@@ -93,6 +210,8 @@ int main(int argc, char **argv)
int rx_extany = 0;
int asc = 0;
int color = 0;
int uds_output = 0;
int is_ff = 0;
int timestamp = 0;
int datidx = 0;
unsigned long fflen = 0;
@@ -103,7 +222,7 @@ int main(int argc, char **argv)
last_tv.tv_sec = 0;
last_tv.tv_usec = 0;
while ((opt = getopt(argc, argv, "s:d:ax:X:ct:?")) != -1) {
while ((opt = getopt(argc, argv, "s:d:ax:X:ct:u?")) != -1) {
switch (opt) {
case 's':
src = strtoul(optarg, (char **)NULL, 16);
@@ -151,6 +270,10 @@ int main(int argc, char **argv)
}
break;
case 'u':
uds_output = 1;
break;
case '?':
print_usage(basename(argv[0]));
exit(0);
@@ -213,65 +336,66 @@ int main(int argc, char **argv)
if (nbytes < 0) {
perror("read");
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);
return 1;
} else {
}
if (frame.can_id == src && ext && !extany &&
extaddr != frame.data[0])
continue;
if (frame.can_id == src && ext && !extany && extaddr != frame.data[0])
continue;
if (frame.can_id == dst && rx_ext && !rx_extany &&
rx_extaddr != frame.data[0])
continue;
if (frame.can_id == dst && rx_ext && !rx_extany && rx_extaddr != frame.data[0])
continue;
if (color)
printf("%s", (frame.can_id == src) ? FGRED : FGBLUE);
if (color)
printf("%s", (frame.can_id == src)? FGRED:FGBLUE);
if (timestamp) {
ioctl(s, SIOCGSTAMP, &tv);
if (timestamp) {
ioctl(s, SIOCGSTAMP, &tv);
switch (timestamp) {
case 'a': /* absolute with timestamp */
printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
break;
case 'A': /* absolute with date */
{
struct tm tm;
char timestring[25];
tm = *localtime(&tv.tv_sec);
strftime(timestring, 24, "%Y-%m-%d %H:%M:%S", &tm);
printf("(%s.%06ld) ", timestring, tv.tv_usec);
}
switch (timestamp) {
case 'a': /* absolute with timestamp */
printf("(%lu.%06lu) ", tv.tv_sec, tv.tv_usec);
break;
case 'd': /* delta */
case 'z': /* starting with zero */
{
struct timeval diff;
case 'A': /* absolute with date */
{
struct tm tm;
char timestring[25];
if (last_tv.tv_sec == 0) /* first init */
last_tv = tv;
diff.tv_sec = tv.tv_sec - last_tv.tv_sec;
diff.tv_usec = tv.tv_usec - last_tv.tv_usec;
if (diff.tv_usec < 0)
diff.tv_sec--, diff.tv_usec += 1000000;
if (diff.tv_sec < 0)
diff.tv_sec = diff.tv_usec = 0;
printf("(%ld.%06ld) ", diff.tv_sec, diff.tv_usec);
tm = *localtime(&tv.tv_sec);
strftime(timestring, 24, "%Y-%m-%d %H:%M:%S",
&tm);
printf("(%s.%06lu) ", timestring, tv.tv_usec);
} break;
if (timestamp == 'd')
last_tv = tv; /* update for delta calculation */
}
case 'd': /* delta */
case 'z': /* starting with zero */
{
struct timeval diff;
if (last_tv.tv_sec == 0) /* first init */
last_tv = tv;
diff.tv_sec = tv.tv_sec - last_tv.tv_sec;
diff.tv_usec = tv.tv_usec - last_tv.tv_usec;
if (diff.tv_usec < 0)
diff.tv_sec--, diff.tv_usec += 1000000;
if (diff.tv_sec < 0)
diff.tv_sec = diff.tv_usec = 0;
printf("(%lu.%06lu) ", diff.tv_sec,
diff.tv_usec);
if (timestamp == 'd')
last_tv =
tv; /* update for delta calculation */
} break;
default: /* no timestamp output */
break;
default: /* no timestamp output */
break;
}
}
}
if (frame.can_id & CAN_EFF_FLAG)
printf(" %s %8X", argv[optind], frame.can_id & CAN_EFF_MASK);
@@ -288,9 +412,10 @@ int main(int argc, char **argv)
datidx = 0;
n_pci = frame.data[ext];
switch (n_pci & 0xF0) {
case 0x00:
is_ff = 1;
if (n_pci & 0xF) {
printf("[SF] ln: %-4d data:", n_pci & 0xF);
datidx = ext+1;
@@ -301,6 +426,7 @@ int main(int argc, char **argv)
break;
case 0x10:
is_ff = 1;
fflen = ((n_pci & 0x0F)<<8) + frame.data[ext+1];
if (fflen)
datidx = ext+2;
@@ -362,13 +488,21 @@ int main(int argc, char **argv)
}
printf("'");
}
if (uds_output && is_ff) {
int offset = 3;
if (asc)
offset = 1;
printf("%*s", ((7-ext) - (frame.len-datidx))*offset + 3,
" - ");
print_uds_message(frame.data[datidx], frame.data[datidx+2]);
is_ff = 0;
}
}
if (color)
printf("%s", ATTRESET);
printf("\n");
fflush(stdout);
}
}
close(s);
+32 -27
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* isotpperf.c - ISO15765-2 protocol performance visualisation
*
@@ -41,21 +42,22 @@
*
*/
#include <libgen.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <libgen.h>
#include <time.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <linux/sockios.h>
#define NO_CAN_ID 0xFFFFFFFFU
#define PERCENTRES 2 /* resolution in percent for bargraph */
@@ -63,11 +65,13 @@
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, "Options: -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, " -x <addr> (extended addressing mode)\n");
fprintf(stderr, " -X <addr> (extended addressing mode (rx addr))\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, " -x <addr> (extended addressing mode)\n");
fprintf(stderr, " -X <addr> (extended addressing mode (rx addr))\n");
fprintf(stderr, "\nCAN IDs and addresses are given and expected in hexadecimal values.\n");
fprintf(stderr, "\n");
}
@@ -219,19 +223,21 @@ int main(int argc, char **argv)
ret = nbytes;
running = 0;
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);
ret = nbytes;
running = 0;
continue;
} else {
if (rcvlen) {
/* make sure to process only the detected PDU CAN frame type */
if (canfd_on && (nbytes != CANFD_MTU))
continue;
if (!canfd_on && (nbytes != CAN_MTU))
continue;
}
}
if (rcvlen) {
/* make sure to process only the detected PDU CAN frame type */
if (canfd_on && (nbytes != CANFD_MTU))
continue;
if (!canfd_on && (nbytes != CAN_MTU))
continue;
}
/* check extended address if provided */
if (ext && extaddr != frame.data[0])
@@ -245,13 +251,13 @@ int main(int argc, char **argv)
n_pci = frame.data[rx_ext];
/* check flow control PCI only */
if ((n_pci & 0xF0) == 0x30) {
bs = frame.data[rx_ext+1];
stmin = frame.data[rx_ext+2];
} else
if ((n_pci & 0xF0) != 0x30)
continue;
bs = frame.data[rx_ext + 1];
stmin = frame.data[rx_ext + 2];
}
/* data content starts and index datidx */
datidx = 0;
@@ -351,7 +357,7 @@ int main(int argc, char **argv)
if (rcvlen) {
if (rcvlen > fflen)
rcvlen = fflen;
percent = (rcvlen * 100 / fflen);
printf("\r %3lu%% ", percent);
@@ -361,7 +367,7 @@ int main(int argc, char **argv)
percent = 100;
for (i=0; i < NUMBAR; i++){
if (i < percent/PERCENTRES)
if (i < (int)(percent/PERCENTRES))
printf("X");
else
printf(".");
@@ -393,7 +399,7 @@ int main(int argc, char **argv)
/* check devisor to be not zero */
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) /
(diff_tv.tv_sec * 1000 + diff_tv.tv_usec / 1000));
} else
@@ -404,7 +410,6 @@ int main(int argc, char **argv)
fflen = rcvlen = 0;
}
fflush(stdout);
}
}
close(s);
+17 -15
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* isotprecv.c
*
@@ -41,16 +42,16 @@
*
*/
#include <libgen.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <linux/can.h>
#include <linux/can/isotp.h>
@@ -61,17 +62,18 @@
void print_usage(char *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, " -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, " -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, " -b <bs> (blocksize. 0 = off)\n");
fprintf(stderr, " -m <val> (STmin in ms/ns. See spec.)\n");
fprintf(stderr, " -f <time ns> (force rx stmin value in nanosecs)\n");
fprintf(stderr, " -w <num> (max. wait frame transmissions.)\n");
fprintf(stderr, " -l (loop: do not exit after pdu receiption.)\n");
fprintf(stderr, " -L <mtu>:<tx_dl>:<tx_flags> (link layer options for CAN FD)\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, " -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 <mode> (check rx padding for (l)ength (c)ontent (a)ll)\n");
fprintf(stderr, " -b <bs> (blocksize. 0 = off)\n");
fprintf(stderr, " -m <val> (STmin in ms/ns. See spec.)\n");
fprintf(stderr, " -f <time ns> (force rx stmin value in nanosecs)\n");
fprintf(stderr, " -w <num> (max. wait frame transmissions.)\n");
fprintf(stderr, " -l (loop: do not exit after pdu reception.)\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, "The pdu data is written on STDOUT in space separated ASCII hex values.\n");
fprintf(stderr, "\n");
+20 -13
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* isotpsend.c
*
@@ -41,16 +42,16 @@
*
*/
#include <libgen.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <linux/can.h>
#include <linux/can/isotp.h>
@@ -61,15 +62,17 @@
void print_usage(char *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, " -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 <mode> (check rx padding for (l)ength (c)ontent (a)ll)\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, " -D <len> (send a fixed PDU with len bytes - no STDIN data)\n");
fprintf(stderr, " -L <mtu>:<tx_dl>:<tx_flags> (link layer options for CAN FD)\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 <mode> (check rx padding for (l)ength (c)ontent (a)ll)\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, " -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, "\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, "\n");
@@ -91,7 +94,7 @@ int main(int argc, char **argv)
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) {
case 's':
addr.can_addr.tp.tx_id = strtoul(optarg, (char **)NULL, 16);
@@ -174,6 +177,10 @@ int main(int argc, char **argv)
}
break;
case 'b':
opts.flags |= CAN_ISOTP_WAIT_TX_DONE;
break;
case 'L':
if (sscanf(optarg, "%hhu:%hhu:%hhu",
&llopts.mtu,
+36 -31
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* isotpserver.c
*
@@ -56,21 +57,22 @@
*
*/
#include <errno.h>
#include <libgen.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <libgen.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <time.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 <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/isotp.h>
@@ -99,28 +101,29 @@ void childdied(int i)
void print_usage(char *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, "ip addressing:\n");
fprintf(stderr, " -l <port> * (local port for the server)\n");
fprintf(stderr, "\n");
fprintf(stderr, "ip adressing:\n");
fprintf(stderr, " * -l <port> (local port for the server)\n");
fprintf(stderr, "\n");
fprintf(stderr, "isotp adressing:\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, " -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, "isotp addressing:\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, " -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, "\n");
fprintf(stderr, "padding:\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 [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, "\n");
fprintf(stderr, "rx path: (config, which is sent to the sender / data source)\n");
fprintf(stderr, " -b <bs> (blocksize. 0 = off)\n");
fprintf(stderr, " -m <val> (STmin in ms/ns. See spec.)\n");
fprintf(stderr, " -w <num> (max. wait frame transmissions)\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, " -m <val> (STmin in ms/ns. See spec.)\n");
fprintf(stderr, " -w <num> (max. wait frame transmissions)\n");
fprintf(stderr, "\n");
fprintf(stderr, "tx path: (config, which changes local tx settings)\n");
fprintf(stderr, " -t <time ns> (transmit time in nanosecs)\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, "\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, "\n");
@@ -297,9 +300,13 @@ int main(int argc, char **argv)
saddr.sin_port = htons(local_port);
while(bind(sl,(struct sockaddr*)&saddr, sizeof(saddr)) < 0) {
struct timespec f = {
.tv_nsec = 100 * 1000 * 1000,
};
printf(".");
fflush(NULL);
usleep(100000);
nanosleep(&f, NULL);
}
if (listen(sl, 3) != 0) {
@@ -310,11 +317,9 @@ int main(int argc, char **argv)
while (1) {
sa = accept(sl,(struct sockaddr *)&clientaddr, &sin_size);
if (sa > 0 ){
if (fork())
close(sa);
else
if (!fork())
break;
close(sa);
}
else {
if (errno != EINTR) {
+80 -40
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* isotpsniffer.c - dump ISO15765-2 datagrams using PF_CAN isotp protocol
*
@@ -41,21 +42,23 @@
*
*/
#include <ctype.h>
#include <libgen.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include <time.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "terminal.h"
#include <linux/can.h>
#include <linux/can/isotp.h>
#include "terminal.h"
#include <linux/sockios.h>
#define NO_CAN_ID 0xFFFFFFFFU
@@ -66,13 +69,15 @@
void print_usage(char *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, " -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 - rx addr)\n");
fprintf(stderr, " -c (color mode)\n");
fprintf(stderr, " -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n");
fprintf(stderr, " -f <format> (1 = HEX, 2 = ASCII, 3 = HEX & ASCII - default: %d)\n", FORMAT_DEFAULT);
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, " -x <addr> (extended addressing mode)\n");
fprintf(stderr, " -X <addr> (extended addressing mode - rx addr)\n");
fprintf(stderr, " -c (color mode)\n");
fprintf(stderr, " -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n");
fprintf(stderr, " -f <format> (1 = HEX, 2 = ASCII, 3 = HEX & ASCII - default: %d)\n", FORMAT_DEFAULT);
fprintf(stderr, " -L <mtu>:<tx_dl>:<tx_flags> (link layer options for CAN FD)\n");
fprintf(stderr, " -h <len> (head: print only first <len> bytes)\n");
fprintf(stderr, "\nCAN IDs and addresses are given and expected in hexadecimal values.\n");
fprintf(stderr, "\n");
@@ -96,7 +101,7 @@ void printbuf(unsigned char *buffer, int nbytes, int color, int timestamp,
switch (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;
case 'A': /* absolute with date */
@@ -106,7 +111,7 @@ void printbuf(unsigned char *buffer, int nbytes, int color, int timestamp,
tm = *localtime(&tv->tv_sec);
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;
@@ -123,7 +128,7 @@ void printbuf(unsigned char *buffer, int nbytes, int color, int timestamp,
diff.tv_sec--, diff.tv_usec += 1000000;
if (diff.tv_sec < 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')
*last_tv = *tv; /* update for delta calculation */
@@ -135,7 +140,7 @@ void printbuf(unsigned char *buffer, int nbytes, int color, int timestamp,
}
}
/* the source socket gets pdu data from the detination id */
/* the source socket gets pdu data from the destination id */
printf(" %s %03X [%d] ", candevice, src & CAN_EFF_MASK, nbytes);
if (format & FORMAT_HEX) {
for (i=0; i<nbytes; i++) {
@@ -151,7 +156,7 @@ void printbuf(unsigned char *buffer, int nbytes, int color, int timestamp,
if (format & FORMAT_ASCII) {
printf("'");
for (i=0; i<nbytes; i++) {
if ((buffer[i] > 0x1F) && (buffer[i] < 0x7F))
if (isprint(buffer[i]))
printf("%c", buffer[i]);
else
printf(".");
@@ -173,10 +178,12 @@ void printbuf(unsigned char *buffer, int nbytes, int color, int timestamp,
int main(int argc, char **argv)
{
fd_set rdfs;
int s, t;
int s = -1, t = -1;
struct sockaddr_can addr;
char if_name[IFNAMSIZ];
static struct can_isotp_options opts;
static struct can_isotp_ll_options llopts;
int r = 0;
int opt, quit = 0;
int color = 0;
int head = 0;
@@ -190,7 +197,7 @@ int main(int argc, char **argv)
unsigned char buffer[4096];
int nbytes;
while ((opt = getopt(argc, argv, "s:d:x:X:h:ct:f:?")) != -1) {
while ((opt = getopt(argc, argv, "s:d:x:X:h:ct:f:L:?")) != -1) {
switch (opt) {
case 's':
src = strtoul(optarg, (char **)NULL, 16);
@@ -218,6 +225,17 @@ int main(int argc, char **argv)
format = (atoi(optarg) & (FORMAT_ASCII | FORMAT_HEX));
break;
case 'L':
if (sscanf(optarg, "%hhu:%hhu:%hhu",
&llopts.mtu,
&llopts.tx_dl,
&llopts.tx_flags) != 3) {
printf("unknown link layer options '%s'.\n", optarg);
print_usage(basename(argv[0]));
exit(1);
}
break;
case 'h':
head = atoi(optarg);
break;
@@ -238,35 +256,37 @@ int main(int argc, char **argv)
case '?':
print_usage(basename(argv[0]));
exit(0);
break;
goto out;
default:
fprintf(stderr, "Unknown option %c\n", opt);
print_usage(basename(argv[0]));
exit(1);
break;
goto out;
}
}
if ((argc - optind) != 1 || src == NO_CAN_ID || dst == NO_CAN_ID) {
print_usage(basename(argv[0]));
exit(1);
r = 1;
goto out;
}
if ((opts.flags & CAN_ISOTP_RX_EXT_ADDR) && (!(opts.flags & CAN_ISOTP_EXTEND_ADDR))) {
print_usage(basename(argv[0]));
exit(1);
r = 1;
goto out;
}
if ((s = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP)) < 0) {
perror("socket");
exit(1);
r = 1;
goto out;
}
if ((t = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP)) < 0) {
perror("socket");
exit(1);
r = 1;
goto out;
}
opts.flags |= CAN_ISOTP_LISTEN_MODE;
@@ -284,8 +304,8 @@ int main(int argc, char **argv)
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind");
close(s);
exit(1);
r = 1;
goto out;
}
if (opts.flags & CAN_ISOTP_RX_EXT_ADDR) {
@@ -297,15 +317,25 @@ int main(int argc, char **argv)
opts.rx_ext_address = tmpext;
}
setsockopt(t, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts));
if ((setsockopt(t, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts))) < 0) {
perror("setsockopt");
r = 1;
goto out;
}
if ((llopts.mtu) && (setsockopt(t, SOL_CAN_ISOTP, CAN_ISOTP_LL_OPTS, &llopts, sizeof(llopts))) < 0) {
perror("setsockopt");
r = 1;
goto out;
}
addr.can_addr.tp.tx_id = dst;
addr.can_addr.tp.rx_id = src;
if (bind(t, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind");
close(s);
exit(1);
r = 1;
goto out;
}
while (!quit) {
@@ -330,10 +360,13 @@ int main(int argc, char **argv)
nbytes = read(s, buffer, 4096);
if (nbytes < 0) {
perror("read socket s");
return -1;
r = 1;
goto out;
}
if (nbytes > 4095) {
r = 1;
goto out;
}
if (nbytes > 4095)
return -1;
printbuf(buffer, nbytes, color?2:0, timestamp, format,
&tv, &last_tv, dst, s, if_name, head);
}
@@ -342,16 +375,23 @@ int main(int argc, char **argv)
nbytes = read(t, buffer, 4096);
if (nbytes < 0) {
perror("read socket t");
return -1;
r = 1;
goto out;
}
if (nbytes > 4095) {
r = 1;
goto out;
}
if (nbytes > 4095)
return -1;
printbuf(buffer, nbytes, color?1:0, timestamp, format,
&tv, &last_tv, src, t, if_name, head);
}
}
close(s);
out:
if (s != -1)
close(s);
if (t != -1)
close(t);
return 0;
return r;
}
+38 -32
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* isotptun.c - IP over CAN ISO-TP (ISO15765-2) tunnel / proof-of-concept
*
@@ -47,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 <fcntl.h>
#include <libgen.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <linux/can.h>
#include <linux/can/isotp.h>
@@ -101,23 +102,25 @@ void perror_syslog(const char *s)
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, "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, "Options: -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, " -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, " -L <mtu>:<tx_dl>:<tx_flags> (link layer options for CAN FD)\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, " -t <time ns> (transmit time in nanosecs)\n");
fprintf(stderr, " -b <bs> (blocksize. 0 = off)\n");
fprintf(stderr, " -m <val> (STmin in ms/ns. See spec.)\n");
fprintf(stderr, " -w <num> (max. wait frame transmissions.)\n");
fprintf(stderr, " -D (daemonize to background when tun device created)\n");
fprintf(stderr, " -h (half duplex mode.)\n");
fprintf(stderr, " -v (verbose mode. Print symbols for tunneled msgs.)\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, " -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, " -L <mtu>:<tx_dl>:<tx_flags> (link layer options for CAN FD)\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, " -t <time ns> (transmit time in nanosecs)\n");
fprintf(stderr, " -b <bs> (blocksize. 0 = off)\n");
fprintf(stderr, " -m <val> (STmin in ms/ns. See spec.)\n");
fprintf(stderr, " -w <num> (max. wait frame transmissions.)\n");
fprintf(stderr, " -D (daemonize to background when tun device created)\n");
fprintf(stderr, " -h (half duplex mode.)\n");
fprintf(stderr, " -v (verbose mode. Print symbols for tunneled msgs.)\n");
fprintf(stderr, "\nCAN IDs and addresses are given and expected in hexadecimal values.\n");
fprintf(stderr, "Use e.g. 'ifconfig ctun0 123.123.123.1 pointopoint 123.123.123.2 up'\n");
fprintf(stderr, "to create a point-to-point IP connection on CAN.\n");
@@ -142,7 +145,7 @@ int main(int argc, char **argv)
extern int optind, opterr, optopt;
static int verbose;
unsigned char buffer[BUF_LEN];
static char name[IFNAMSIZ] = DEFAULT_NAME;
static char name[sizeof(ifr.ifr_name)] = DEFAULT_NAME;
int nbytes;
int run_as_daemon = 0;
@@ -163,7 +166,13 @@ int main(int argc, char **argv)
break;
case 'n':
strncpy(name, optarg, IFNAMSIZ-1);
if (strlen(optarg) > sizeof(name) - 1) {
print_usage(basename(argv[0]));
exit(EXIT_FAILURE);
}
/* ensure string termination */
memset(name, 0, sizeof(name));
strncpy(name, optarg, sizeof(name) - 1);
break;
case 'x':
@@ -298,17 +307,14 @@ int main(int argc, char **argv)
}
}
strncpy(ifr.ifr_name, argv[optind], IFNAMSIZ);
ifr.ifr_ifindex = if_nametoindex(ifr.ifr_name);
if (!ifr.ifr_ifindex) {
addr.can_family = AF_CAN;
addr.can_ifindex = if_nametoindex(argv[optind]);
if (!addr.can_ifindex) {
perror_syslog("if_nametoindex");
close(s);
exit(EXIT_FAILURE);
}
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror_syslog("bind");
close(s);
@@ -324,8 +330,8 @@ int main(int argc, char **argv)
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
strncpy(ifr.ifr_name, name, IFNAMSIZ - 1);
ifr.ifr_name[IFNAMSIZ - 1] = '\0';
/* string termination is ensured at commandline option handling */
strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
if (ioctl(t, TUNSETIFF, (void *) &ifr) < 0) {
perror_syslog("ioctl tunfd");
+99 -93
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2011 EIA Electronics
*
@@ -9,29 +10,29 @@
* as published by the Free Software Foundation
*/
#include <signal.h>
#include <time.h>
#include <inttypes.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <err.h>
#include <getopt.h>
#include <error.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <net/if.h>
#include <linux/can.h>
#include <linux/can/j1939.h>
#include <net/if.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
#include "libj1939.h"
static const char help_msg[] =
"jacd: An SAE J1939 address claiming daemon" "\n"
"Usage: jacd [options] NAME [INTF]" "\n"
"\n"
"j1939acd: An SAE J1939 address claiming daemon" "\n"
"Usage: j1939acd [options] NAME [INTF]" "\n"
"Options:\n"
" -v, --verbose Increase verbosity" "\n"
" -r, --range=RANGE Ranges of source addresses" "\n"
" e.g. 80,50-100,200-210 (defaults to 0-253)" "\n"
@@ -41,8 +42,9 @@ static const char help_msg[] =
"\n"
"NAME is the 64bit nodename" "\n"
"\n"
"Example:" "\n"
"jacd -r 100,80-120 -c /tmp/1122334455667788.jacd 1122334455667788" "\n"
"Examples:" "\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
@@ -154,12 +156,12 @@ static int parse_range(char *str)
for (tok = strtok(str, ",;"); tok; tok = strtok(NULL, ",;")) {
a0 = ae = strtoul(tok, &endp, 0);
if (endp <= tok)
error(1, 0, "parsing range '%s'", tok);
err(1, "parsing range '%s'", tok);
if (*endp == '-') {
tok = endp+1;
ae = strtoul(tok, &endp, 0);
if (endp <= tok)
error(1, 0, "parsing addr '%s'", tok);
err(1, "parsing addr '%s'", tok);
if (ae < a0)
ae = a0;
}
@@ -175,14 +177,14 @@ static int parse_range(char *str)
/* j1939 socket */
static const struct j1939_filter filt[] = {
{
.pgn = 0x0ee00,
.pgn_mask = 0x3ff00,
.pgn = J1939_PGN_ADDRESS_CLAIMED,
.pgn_mask = J1939_PGN_PDU1_MAX,
}, {
.pgn = 0x0ea00,
.pgn_mask = 0x3ff00,
.pgn = J1939_PGN_REQUEST,
.pgn_mask = J1939_PGN_PDU1_MAX,
}, {
.pgn = 0x0fed8,
.pgn_mask = 0x3ffff,
.pgn = J1939_PGN_ADDRESS_COMMANDED,
.pgn_mask = J1939_PGN_MAX,
},
};
@@ -195,44 +197,37 @@ static int open_socket(const char *device, uint64_t name)
.can_addr.j1939 = {
.name = name,
.addr = J1939_IDLE_ADDR,
.pgn = 0x0ee00,
.pgn = J1939_NO_PGN,
},
.can_ifindex = if_nametoindex(s.intf),
.can_ifindex = if_nametoindex(device),
};
if (s.verbose)
fprintf(stderr, "- socket(PF_CAN, SOCK_DGRAM, CAN_J1939);\n");
sock = ret = socket(PF_CAN, SOCK_DGRAM, CAN_J1939);
if (ret < 0)
error(1, errno, "socket(j1939)");
if (s.verbose)
fprintf(stderr, "- setsockopt(, SOL_SOCKET, SO_BINDTODEVICE, %s, %zd);\n", device, strlen(device));
ret = setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
device, strlen(device));
if (ret < 0)
error(1, errno, "bindtodevice %s", device);
err(1, "socket(j1939)");
if (s.verbose)
fprintf(stderr, "- setsockopt(, SOL_CAN_J1939, SO_J1939_FILTER, <filter>, %zd);\n", sizeof(filt));
ret = setsockopt(sock, SOL_CAN_J1939, SO_J1939_FILTER,
&filt, sizeof(filt));
if (ret < 0)
error(1, errno, "setsockopt filter");
err(1, "setsockopt filter");
value = 1;
if (s.verbose)
fprintf(stderr, "- setsockopt(, SOL_CAN_J1939, SO_J1939_RECV_OWN, %d, %zd);\n", value, sizeof(value));
ret = setsockopt(sock, SOL_CAN_J1939, SO_J1939_RECV_OWN,
fprintf(stderr, "- setsockopt(, SOL_SOCKET, SO_BROADCAST, %d, %zd);\n", value, sizeof(value));
ret = setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
&value, sizeof(value));
if (ret < 0)
error(1, errno, "setsockopt receive own msgs");
err(1, "setsockopt set broadcast");
if (s.verbose)
fprintf(stderr, "- bind(, %s, %zi);\n", libj1939_addr2str(&saddr), sizeof(saddr));
ret = bind(sock, (void *)&saddr, sizeof(saddr));
if (ret < 0)
error(1, errno, "bind()");
err(1, "bind()");
return sock;
}
@@ -241,15 +236,23 @@ static int repeat_address(int sock, uint64_t name)
{
int ret;
uint8_t dat[8];
static const struct sockaddr_can saddr = {
.can_family = AF_CAN,
.can_addr.j1939 = {
.pgn = J1939_PGN_ADDRESS_CLAIMED,
.addr = J1939_NO_ADDR,
},
};
memcpy(dat, &name, 8);
if (!host_is_little_endian())
bswap(dat, 8);
if (s.verbose)
fprintf(stderr, "- send(, %" PRId64 ", 8, 0);\n", name);
ret = send(sock, dat, 8, 0);
ret = sendto(sock, dat, sizeof(dat), 0, (const struct sockaddr *)&saddr,
sizeof(saddr));
if (must_warn(ret))
error(1, errno, "send address claim for 0x%02x", s.last_sa);
fprintf(stderr, "send address claim for 0x%02x\n", s.last_sa);
return ret;
}
static int claim_address(int sock, uint64_t name, int sa)
@@ -260,7 +263,7 @@ static int claim_address(int sock, uint64_t name, int sa)
.can_addr.j1939 = {
.name = name,
.addr = sa,
.pgn = 0x0ee00,
.pgn = J1939_NO_PGN,
},
.can_ifindex = if_nametoindex(s.intf),
};
@@ -269,7 +272,7 @@ static int claim_address(int sock, uint64_t name, int sa)
fprintf(stderr, "- bind(, %s, %zi);\n", libj1939_addr2str(&saddr), sizeof(saddr));
ret = bind(sock, (void *)&saddr, sizeof(saddr));
if (ret < 0)
error(1, errno, "rebind with sa 0x%02x", sa);
err(1, "rebind with sa 0x%02x", sa);
s.last_sa = sa;
return repeat_address(sock, name);
}
@@ -280,7 +283,7 @@ static int request_addresses(int sock)
int ret;
static const struct sockaddr_can saddr = {
.can_family = AF_CAN,
.can_addr.j1939.pgn = 0x0ea00,
.can_addr.j1939.pgn = J1939_PGN_REQUEST,
.can_addr.j1939.addr = J1939_NO_ADDR,
};
@@ -288,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));
ret = sendto(sock, dat, sizeof(dat), 0, (void *)&saddr, sizeof(saddr));
if (must_warn(ret))
error(1, errno, "send request for address claims");
fprintf(stdout, "send request for address claims");
return ret;
}
@@ -356,13 +359,13 @@ static void install_signal(int sig)
sigfillset(&sigact.sa_mask);
ret = sigaction(sig, &sigact, NULL);
if (ret < 0)
error(1, errno, "sigaction for signal %i", sig);
err(1, "sigaction for signal %i", sig);
}
static void schedule_itimer(int msec)
{
int ret;
struct itimerval val = {};
struct itimerval val = { 0 };
val.it_value.tv_sec = msec / 1000;
val.it_value.tv_usec = (msec % 1000) * 1000;
@@ -372,7 +375,7 @@ static void schedule_itimer(int msec)
ret = setitimer(ITIMER_REAL, &val, NULL);
} while ((ret < 0) && (errno == EINTR));
if (ret < 0)
error(1, errno, "setitimer %i msec", msec);
err(1, "setitimer %i msec", msec);
}
/* dump status */
@@ -380,10 +383,9 @@ static inline int addr_status_mine(int sa)
{
if (sa == s.current_sa)
return '*';
else if (addr[sa].flags & F_USE)
if (addr[sa].flags & F_USE)
return '+';
else
return '-';
return '-';
}
static void dump_status(void)
@@ -413,7 +415,7 @@ static void save_cache(void)
return;
fp = fopen(s.cachefile, "w");
if (!fp)
error(1, errno, "fopen %s, w", s.cachefile);
err(1, "fopen %s, w", s.cachefile);
time(&t);
fprintf(fp, "# saved on %s\n", ctime(&t));
@@ -436,7 +438,7 @@ static void restore_cache(void)
if (!fp) {
if (ENOENT == errno)
return;
error(1, errno, "fopen %s, r", s.cachefile);
err(1, "fopen %s, r", s.cachefile);
}
while (!feof(fp)) {
ret = getline(&line, &sz, fp);
@@ -458,7 +460,7 @@ static void restore_cache(void)
/* main */
int main(int argc, char *argv[])
{
int ret, sock, pgn, sa, opt;
int ret, sock, sock_rx, pgn, sa, opt;
socklen_t slen;
uint8_t dat[9];
struct sockaddr_can saddr;
@@ -469,31 +471,34 @@ int main(int argc, char *argv[])
#endif
/* argument parsing */
while ((opt = getopt_long(argc, argv, optstring, long_opts, NULL)) != -1)
switch (opt) {
case 'v':
++s.verbose;
break;
case 'c':
s.cachefile = optarg;
break;
case 'r':
s.ranges = optarg;
break;
case 'a':
s.current_sa = strtoul(optarg, 0, 0);
break;
case 'p':
switch (opt) {
case 'v':
++s.verbose;
break;
case 'c':
s.cachefile = optarg;
break;
case 'r':
s.ranges = optarg;
break;
case 'a':
s.current_sa = strtoul(optarg, 0, 0);
break;
case 'p':
#ifdef _GNU_SOURCE
asprintf(&program_invocation_name, "%s.%s", program_invocation_short_name, optarg);
if (asprintf(&program_invocation_name, "%s.%s",
program_invocation_short_name, optarg) < 0)
err(1, "asprintf(program invocation name)");
#else
error(0, 0, "compile with -D_GNU_SOURCE to use -p");
err(0, "compile with -D_GNU_SOURCE to use -p");
#endif
break;
default:
fputs(help_msg, stderr);
exit(1);
break;
}
break;
default:
fputs(help_msg, stderr);
exit(1);
break;
}
if (argv[optind])
s.name = strtoull(argv[optind++], 0, 16);
if (argv[optind])
@@ -505,19 +510,20 @@ int main(int argc, char *argv[])
ret = parse_range(s.ranges);
if (!ret)
error(1, 0, "no addresses in range");
err(1, "no addresses in range");
if ((s.current_sa < J1939_IDLE_ADDR) && !(addr[s.current_sa].flags & F_USE)) {
if (s.verbose)
error(0, 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;
}
if (s.verbose)
error(0, 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)
error(1, 0, "bad arguments");
err(1, "bad arguments");
ret = sock = open_socket(s.intf, s.name);
sock_rx = open_socket(s.intf, s.name);
install_signal(SIGTERM);
install_signal(SIGINT);
@@ -534,7 +540,7 @@ int main(int argc, char *argv[])
case STATE_INITIAL:
ret = request_addresses(sock);
if (ret < 0)
error(1, errno, "could not sent initial request");
err(1, "could not sent initial request");
s.state = STATE_REQ_SENT;
break;
case STATE_REQ_PENDING:
@@ -544,7 +550,7 @@ int main(int argc, char *argv[])
/* claim addr */
sa = choose_new_sa(s.name, s.current_sa);
if (sa == J1939_IDLE_ADDR)
error(1, 0, "no free address to use");
err(1, "no free address to use");
ret = claim_address(sock, s.name, sa);
if (ret < 0)
schedule_itimer(50);
@@ -561,23 +567,23 @@ int main(int argc, char *argv[])
}
slen = sizeof(saddr);
ret = recvfrom(sock, dat, sizeof(dat), 0, (void *)&saddr, &slen);
ret = recvfrom(sock_rx, dat, sizeof(dat), 0, (void *)&saddr, &slen);
if (ret < 0) {
if (EINTR == errno)
continue;
error(1, errno, "recvfrom()");
err(1, "recvfrom()");
}
switch (saddr.can_addr.j1939.pgn) {
case 0x0ea00:
case J1939_PGN_REQUEST:
if (ret < 3)
break;
pgn = dat[0] + (dat[1] << 8) + ((dat[2] & 0x03) << 16);
if (pgn != 0x0ee00)
if (pgn != J1939_PGN_ADDRESS_CLAIMED)
/* not interested */
break;
if (s.state == STATE_REQ_SENT) {
if (s.verbose)
error(0, 0, "request sent, pending for 1250 ms");
fprintf(stderr, "- request sent, pending for 1250 ms\n");
schedule_itimer(1250);
s.state = STATE_REQ_PENDING;
} else if (s.state == STATE_OPERATIONAL) {
@@ -586,7 +592,7 @@ int main(int argc, char *argv[])
schedule_itimer(50);
}
break;
case 0x0ee00:
case J1939_PGN_ADDRESS_CLAIMED:
if (saddr.can_addr.j1939.addr >= J1939_IDLE_ADDR) {
sa = lookup_name(saddr.can_addr.j1939.name);
if (sa < J1939_IDLE_ADDR)
@@ -604,17 +610,17 @@ int main(int argc, char *argv[])
addr[sa].flags |= F_SEEN;
if (s.name == saddr.can_addr.j1939.name) {
/* ourselve, disable itimer */
/* ourselves, disable itimer */
s.current_sa = sa;
if (s.verbose)
error(0, 0, "claimed 0x%02x", sa);
fprintf(stderr, "- claimed 0x%02x\n", sa);
} else if (sa == s.current_sa) {
if (s.verbose)
error(0, 0, "address collision for 0x%02x", sa);
fprintf(stderr, "- address collision for 0x%02x\n", sa);
if (s.name > saddr.can_addr.j1939.name) {
sa = choose_new_sa(s.name, sa);
if (sa == J1939_IDLE_ADDR) {
error(0, 0, "no address left");
fprintf(stdout, "no address left");
/* put J1939_IDLE_ADDR in cache file */
s.current_sa = sa;
goto done;
@@ -625,7 +631,7 @@ int main(int argc, char *argv[])
schedule_itimer(50);
}
break;
case 0x0fed8:
case J1939_PGN_ADDRESS_COMMANDED:
if (!host_is_little_endian())
bswap(dat, 8);
memcpy(&cmd_name, dat, 8);
@@ -639,7 +645,7 @@ int main(int argc, char *argv[])
}
done:
if (s.verbose)
error(0, 0, "shutdown");
fprintf(stderr, "- shutdown\n");
claim_address(sock, s.name, J1939_IDLE_ADDR);
save_cache();
return 0;
+698
View File
@@ -0,0 +1,698 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@pengutronix.de>
*/
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <net/if.h>
#include <poll.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <linux/errqueue.h>
#include <linux/net_tstamp.h>
#include <linux/netlink.h>
#include <linux/socket.h>
#include "libj1939.h"
#define J1939_MAX_ETP_PACKET_SIZE (7 * 0x00ffffff)
#define JCAT_BUF_SIZE (1000 * 1024)
/*
* min()/max()/clamp() macros that also do
* strict type-checking.. See the
* "unnecessary" pointer comparison.
*/
#define min(x, y) ({ \
typeof(x) _min1 = (x); \
typeof(y) _min2 = (y); \
(void) (&_min1 == &_min2); \
_min1 < _min2 ? _min1 : _min2; })
struct j1939cat_stats {
int err;
uint32_t tskey;
uint32_t send;
};
struct j1939cat_priv {
int sock;
int infile;
int outfile;
size_t max_transfer;
unsigned long repeat;
unsigned long round;
int todo_prio;
bool valid_peername;
bool todo_recv;
bool todo_filesize;
bool todo_connect;
int todo_broadcast;
unsigned long polltimeout;
struct sockaddr_can sockname;
struct sockaddr_can peername;
struct sock_extended_err *serr;
struct scm_timestamping *tss;
struct j1939cat_stats stats;
};
static const char help_msg[] =
"j1939cat: netcat-like tool for j1939\n"
"Usage: j1939cat [options] FROM TO\n"
" FROM / TO - or [IFACE][:[SA][,[PGN][,NAME]]]\n"
"Options:\n"
" -i <infile> (default stdin)\n"
" -s <size> Set maximal transfer size. Default: 117440505 byte\n"
" -r Receive data\n"
" -P <timeout> poll timeout in milliseconds before sending data.\n"
" With this option send() will be used with MSG_DONTWAIT flag.\n"
" -R <count> Set send repeat count. Default: 1\n"
" -B Allow to send and receive broadcast packets.\n"
"\n"
"Example:\n"
"j1939cat -i some_file_to_send can0:0x80 :0x90,0x12300\n"
"j1939cat can0:0x90 -r > /tmp/some_file_to_receive\n"
"\n"
;
static const char optstring[] = "?hi:vs:rp:P:R:B";
static void j1939cat_init_sockaddr_can(struct sockaddr_can *sac)
{
sac->can_family = AF_CAN;
sac->can_addr.j1939.addr = J1939_NO_ADDR;
sac->can_addr.j1939.name = J1939_NO_NAME;
sac->can_addr.j1939.pgn = J1939_NO_PGN;
}
static ssize_t j1939cat_send_one(struct j1939cat_priv *priv, int out_fd,
const void *buf, size_t buf_size)
{
ssize_t num_sent;
int flags = 0;
if (priv->polltimeout)
flags |= MSG_DONTWAIT;
if (priv->valid_peername && !priv->todo_connect)
num_sent = sendto(out_fd, buf, buf_size, flags,
(struct sockaddr *)&priv->peername,
sizeof(priv->peername));
else
num_sent = send(out_fd, buf, buf_size, flags);
if (num_sent == -1) {
warn("%s: transfer error: %i", __func__, -errno);
return -errno;
}
if (num_sent == 0) /* Should never happen */ {
warn("%s: transferred 0 bytes", __func__);
return -EINVAL;
}
if (num_sent > (ssize_t)buf_size) /* Should never happen */ {
warn("%s: send more then read", __func__);
return -EINVAL;
}
return num_sent;
}
static void j1939cat_print_timestamp(struct j1939cat_priv *priv, const char *name,
struct timespec *cur)
{
struct j1939cat_stats *stats = &priv->stats;
if (!(cur->tv_sec | cur->tv_nsec))
return;
fprintf(stderr, " %s: %lu s %lu us (seq=%u, send=%u)",
name, cur->tv_sec, cur->tv_nsec / 1000,
stats->tskey, stats->send);
fprintf(stderr, "\n");
}
static const char *j1939cat_tstype_to_str(int tstype)
{
switch (tstype) {
case SCM_TSTAMP_SCHED:
return " ENQ";
case SCM_TSTAMP_SND:
return " SND";
case SCM_TSTAMP_ACK:
return " ACK";
default:
return " unk";
}
}
/* Check the stats of SCM_TIMESTAMPING_OPT_STATS */
static void j1939cat_scm_opt_stats(struct j1939cat_priv *priv, void *buf, int len)
{
struct j1939cat_stats *stats = &priv->stats;
int offset = 0;
while (offset < len) {
struct nlattr *nla = (struct nlattr *) ((char *)buf + offset);
switch (nla->nla_type) {
case J1939_NLA_BYTES_ACKED:
stats->send = *(uint32_t *)((char *)nla + NLA_HDRLEN);
break;
default:
warnx("not supported J1939_NLA field\n");
}
offset += NLA_ALIGN(nla->nla_len);
}
}
static int j1939cat_extract_serr(struct j1939cat_priv *priv)
{
struct j1939cat_stats *stats = &priv->stats;
struct sock_extended_err *serr = priv->serr;
struct scm_timestamping *tss = priv->tss;
switch (serr->ee_origin) {
case SO_EE_ORIGIN_TIMESTAMPING:
/*
* We expect here following patterns:
* serr->ee_info == SCM_TSTAMP_ACK
* Activated with SOF_TIMESTAMPING_TX_ACK
* or
* serr->ee_info == SCM_TSTAMP_SCHED
* Activated with SOF_TIMESTAMPING_SCHED
* and
* serr->ee_data == tskey
* session message counter which is activate
* with SOF_TIMESTAMPING_OPT_ID
* the serr->ee_errno should be ENOMSG
*/
if (serr->ee_errno != ENOMSG)
warnx("serr: expected ENOMSG, got: %i",
serr->ee_errno);
stats->tskey = serr->ee_data;
j1939cat_print_timestamp(priv, j1939cat_tstype_to_str(serr->ee_info),
&tss->ts[0]);
if (serr->ee_info == SCM_TSTAMP_SCHED)
return -EINTR;
return 0;
case SO_EE_ORIGIN_LOCAL:
/*
* The serr->ee_origin == SO_EE_ORIGIN_LOCAL is
* currently used to notify about locally
* detected protocol/stack errors.
* Following patterns are expected:
* serr->ee_info == J1939_EE_INFO_TX_ABORT
* is used to notify about session TX
* abort.
* serr->ee_data == tskey
* session message counter which is activate
* with SOF_TIMESTAMPING_OPT_ID
* serr->ee_errno == actual error reason
* error reason is converted from J1939
* abort to linux error name space.
*/
if (serr->ee_info != J1939_EE_INFO_TX_ABORT)
warnx("serr: unknown ee_info: %i",
serr->ee_info);
j1939cat_print_timestamp(priv, " ABT", &tss->ts[0]);
warnx("serr: tx error: %i, %s", serr->ee_errno, strerror(serr->ee_errno));
return serr->ee_errno;
default:
warnx("serr: wrong origin: %u", serr->ee_origin);
}
return 0;
}
static int j1939cat_parse_cm(struct j1939cat_priv *priv, struct cmsghdr *cm)
{
const size_t hdr_len = CMSG_ALIGN(sizeof(struct cmsghdr));
if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_TIMESTAMPING) {
priv->tss = (void *)CMSG_DATA(cm);
} else if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_TIMESTAMPING_OPT_STATS) {
void *jstats = (void *)CMSG_DATA(cm);
/* Activated with SOF_TIMESTAMPING_OPT_STATS */
j1939cat_scm_opt_stats(priv, jstats, cm->cmsg_len - hdr_len);
} else if (cm->cmsg_level == SOL_CAN_J1939 &&
cm->cmsg_type == SCM_J1939_ERRQUEUE) {
priv->serr = (void *)CMSG_DATA(cm);
} else
warnx("serr: not supported type: %d.%d",
cm->cmsg_level, cm->cmsg_type);
return 0;
}
static int j1939cat_recv_err(struct j1939cat_priv *priv)
{
char control[100];
struct cmsghdr *cm;
int ret;
struct msghdr msg = {
.msg_control = control,
.msg_controllen = sizeof(control),
};
ret = recvmsg(priv->sock, &msg, MSG_ERRQUEUE);
if (ret == -1)
err(EXIT_FAILURE, "recvmsg error notification: %i", errno);
if (msg.msg_flags & MSG_CTRUNC)
err(EXIT_FAILURE, "recvmsg error notification: truncated");
priv->serr = NULL;
priv->tss = NULL;
for (cm = CMSG_FIRSTHDR(&msg); cm && cm->cmsg_len;
cm = CMSG_NXTHDR(&msg, cm)) {
j1939cat_parse_cm(priv, cm);
if (priv->serr && priv->tss)
return j1939cat_extract_serr(priv);
}
return 0;
}
static int j1939cat_send_loop(struct j1939cat_priv *priv, int out_fd, char *buf,
size_t buf_size)
{
struct j1939cat_stats *stats = &priv->stats;
ssize_t count;
char *tmp_buf = buf;
unsigned int events = POLLOUT | POLLERR;
bool tx_done = false;
count = buf_size;
while (!tx_done) {
ssize_t num_sent = 0;
if (priv->polltimeout) {
struct pollfd fds = {
.fd = priv->sock,
.events = events,
};
int ret;
ret = poll(&fds, 1, priv->polltimeout);
if (ret == -EINTR)
continue;
if (ret < 0)
return -errno;
if (!ret)
return -ETIME;
if (!(fds.revents & events)) {
warn("%s: something else is wrong", __func__);
return -EIO;
}
if (fds.revents & POLLERR) {
ret = j1939cat_recv_err(priv);
if (ret == -EINTR)
continue;
if (ret)
return ret;
if ((priv->repeat - 1) == stats->tskey)
tx_done = true;
}
if (fds.revents & POLLOUT) {
num_sent = j1939cat_send_one(priv, out_fd, tmp_buf, count);
if (num_sent < 0)
return num_sent;
}
} else {
num_sent = j1939cat_send_one(priv, out_fd, tmp_buf, count);
if (num_sent < 0)
return num_sent;
}
count -= num_sent;
tmp_buf += num_sent;
if (buf + buf_size < tmp_buf + count) {
warn("%s: send buffer is bigger than the read buffer",
__func__);
return -EINVAL;
}
if (!count) {
if (priv->repeat == priv->round)
events = POLLERR;
else
tx_done = true;
}
}
return 0;
}
static int j1939cat_sendfile(struct j1939cat_priv *priv, int out_fd, int in_fd,
off_t *offset, size_t count)
{
int ret = EXIT_SUCCESS;
off_t orig = 0;
char *buf;
ssize_t num_read;
size_t to_read, buf_size;
buf_size = min(priv->max_transfer, count);
buf = malloc(buf_size);
if (!buf) {
warn("can't allocate buf");
ret = EXIT_FAILURE;
goto do_nofree;
}
if (offset) {
/* Save current file offset and set offset to value in '*offset' */
orig = lseek(in_fd, 0, SEEK_CUR);
if (orig == -1) {
ret = EXIT_FAILURE;
goto do_free;
}
if (lseek(in_fd, *offset, SEEK_SET) == -1) {
ret = EXIT_FAILURE;
goto do_free;
}
}
while (count > 0) {
to_read = min(buf_size, count);
num_read = read(in_fd, buf, to_read);
if (num_read == -1) {
ret = EXIT_FAILURE;
goto do_free;
}
if (num_read == 0)
break; /* EOF */
ret = j1939cat_send_loop(priv, out_fd, buf, num_read);
if (ret)
goto do_free;
count -= num_read;
}
if (offset) {
/* Return updated file offset in '*offset', and reset the file offset
to the value it had when we were called. */
*offset = lseek(in_fd, 0, SEEK_CUR);
if (*offset == -1) {
ret = EXIT_FAILURE;
goto do_free;
}
if (lseek(in_fd, orig, SEEK_SET) == -1) {
ret = EXIT_FAILURE;
goto do_free;
}
}
do_free:
free(buf);
do_nofree:
return ret;
}
static size_t j1939cat_get_file_size(int fd)
{
off_t offset;
offset = lseek(fd, 0, SEEK_END);
if (offset == -1)
err(1, "%s lseek()\n", __func__);
if (lseek(fd, 0, SEEK_SET) == -1)
err(1, "%s lseek() start\n", __func__);
return offset;
}
static int j1939cat_send(struct j1939cat_priv *priv)
{
unsigned int size = 0;
unsigned int i;
int ret;
if (priv->todo_filesize)
size = j1939cat_get_file_size(priv->infile);
if (!size)
return EXIT_FAILURE;
for (i = 0; i < priv->repeat; i++) {
priv->round++;
ret = j1939cat_sendfile(priv, priv->sock, priv->infile, NULL, size);
if (ret)
break;
if (lseek(priv->infile, 0, SEEK_SET) == -1)
err(1, "%s lseek() start\n", __func__);
}
return ret;
}
static int j1939cat_recv_one(struct j1939cat_priv *priv, uint8_t *buf, size_t buf_size)
{
int ret;
ret = recv(priv->sock, buf, buf_size, 0);
if (ret < 0) {
warn("recvf()");
return EXIT_FAILURE;
}
ret = write(priv->outfile, buf, ret);
if (ret < 0) {
warn("write stdout()");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
static int j1939cat_recv(struct j1939cat_priv *priv)
{
int ret = EXIT_SUCCESS;
size_t buf_size;
uint8_t *buf;
buf_size = priv->max_transfer;
buf = malloc(buf_size);
if (!buf) {
warn("can't allocate rx buf");
return EXIT_FAILURE;;
}
while (priv->todo_recv) {
ret = j1939cat_recv_one(priv, buf, buf_size);
if (ret)
break;
}
free(buf);
return ret;
}
static int j1939cat_sock_prepare(struct j1939cat_priv *priv)
{
unsigned int sock_opt;
int value;
int ret;
/* open socket */
priv->sock = socket(PF_CAN, SOCK_DGRAM, CAN_J1939);
if (priv->sock < 0) {
warn("socket(j1939)");
return EXIT_FAILURE;
}
if (priv->todo_prio >= 0) {
ret = setsockopt(priv->sock, SOL_CAN_J1939, SO_J1939_SEND_PRIO,
&priv->todo_prio, sizeof(priv->todo_prio));
if (ret < 0) {
warn("set priority %i", priv->todo_prio);
return EXIT_FAILURE;
}
}
value = 1;
ret = setsockopt(priv->sock, SOL_CAN_J1939, SO_J1939_ERRQUEUE, &value,
sizeof(value));
if (ret < 0) {
warn("set recverr");
return EXIT_FAILURE;
}
sock_opt = SOF_TIMESTAMPING_SOFTWARE |
SOF_TIMESTAMPING_OPT_CMSG |
SOF_TIMESTAMPING_TX_ACK |
SOF_TIMESTAMPING_TX_SCHED |
SOF_TIMESTAMPING_OPT_STATS | SOF_TIMESTAMPING_OPT_TSONLY |
SOF_TIMESTAMPING_OPT_ID;
if (setsockopt(priv->sock, SOL_SOCKET, SO_TIMESTAMPING,
(char *) &sock_opt, sizeof(sock_opt)))
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));
if (ret < 0) {
warn("bind()");
return EXIT_FAILURE;
}
if (!priv->todo_connect)
return EXIT_SUCCESS;
if (!priv->valid_peername) {
warn("no peername supplied");
return EXIT_FAILURE;
}
ret = connect(priv->sock, (void *)&priv->peername,
sizeof(priv->peername));
if (ret < 0) {
warn("connect()");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
static int j1939cat_parse_args(struct j1939cat_priv *priv, int argc, char *argv[])
{
int opt;
/* argument parsing */
while ((opt = getopt(argc, argv, optstring)) != -1)
switch (opt) {
case 'i':
priv->infile = open(optarg, O_RDONLY);
if (priv->infile == -1)
err(EXIT_FAILURE, "can't open input file");
priv->todo_filesize = 1;
break;
case 's':
priv->max_transfer = strtoul(optarg, NULL, 0);
if (priv->max_transfer > J1939_MAX_ETP_PACKET_SIZE)
err(EXIT_FAILURE,
"used value (%zu) is bigger then allowed maximal size: %u.\n",
priv->max_transfer,
J1939_MAX_ETP_PACKET_SIZE);
break;
case 'r':
priv->todo_recv = 1;
break;
case 'p':
priv->todo_prio = strtoul(optarg, NULL, 0);
break;
case 'P':
priv->polltimeout = strtoul(optarg, NULL, 0);
break;
case 'c':
priv->todo_connect = 1;
break;
case 'R':
priv->repeat = strtoul(optarg, NULL, 0);
if (priv->repeat < 1)
err(EXIT_FAILURE,
"send/repeat count can't be less then 1\n");
break;
case 'B':
priv->todo_broadcast = 1;
break;
case 'h': /*fallthrough*/
default:
fputs(help_msg, stderr);
return EXIT_FAILURE;
}
if (argv[optind]) {
if (strcmp("-", argv[optind]) != 0)
libj1939_parse_canaddr(argv[optind], &priv->sockname);
optind++;
}
if (argv[optind]) {
if (strcmp("-", argv[optind]) != 0) {
libj1939_parse_canaddr(argv[optind], &priv->peername);
priv->valid_peername = 1;
}
optind++;
}
return EXIT_SUCCESS;
}
int main(int argc, char *argv[])
{
struct j1939cat_priv *priv;
int ret = 0;
priv = calloc(1, sizeof(*priv));
if (!priv)
err(EXIT_FAILURE, "can't allocate priv");
priv->todo_prio = -1;
priv->infile = STDIN_FILENO;
priv->outfile = STDOUT_FILENO;
priv->max_transfer = J1939_MAX_ETP_PACKET_SIZE;
priv->polltimeout = 100000;
priv->repeat = 1;
j1939cat_init_sockaddr_can(&priv->sockname);
j1939cat_init_sockaddr_can(&priv->peername);
ret = j1939cat_parse_args(priv, argc, argv);
if (ret)
return ret;
ret = j1939cat_sock_prepare(priv);
if (ret)
return ret;
if (priv->todo_recv)
ret = j1939cat_recv(priv);
else
ret = j1939cat_send(priv);
close(priv->infile);
close(priv->outfile);
close(priv->sock);
return ret;
}
+52 -52
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2011 EIA Electronics
*
@@ -9,19 +10,19 @@
* as published by the Free Software Foundation
*/
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <err.h>
#include <getopt.h>
#include <error.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
#include "libj1939.h"
@@ -29,9 +30,9 @@
* getopt
*/
static const char help_msg[] =
"jspy: An SAE J1939 spy utility" "\n"
"Usage: jspy [OPTION...] [[IFACE:][NAME|SA][,PGN]]" "\n"
"\n"
"j1939spy: An SAE J1939 spy utility" "\n"
"Usage: j1939spy [OPTION...] [[IFACE:][NAME|SA][,PGN]]" "\n"
"Options:\n"
" -v, --verbose Increase verbosity" "\n"
" -P, --promisc Run in promiscuous mode" "\n"
" (= receive traffic not for this ECU)" "\n"
@@ -74,7 +75,7 @@ static struct {
};
/*
* usefull buffers
* useful buffers
*/
static const int ival_1 = 1;
@@ -94,8 +95,8 @@ static uint8_t *buf;
*/
int main(int argc, char **argv)
{
int ret, sock, j, opt;
unsigned int len;
int ret, sock, opt;
unsigned int j, len;
struct timeval tref, tdut, ttmp;
struct sockaddr_can src;
struct j1939_filter filt;
@@ -104,52 +105,51 @@ int main(int argc, char **argv)
uint64_t dst_name;
long recvflags;
#ifdef _GNU_SOURCE
program_invocation_name = program_invocation_short_name;
#endif
/* argument parsing */
while ((opt = getopt_long(argc, argv, optstring, long_opts, NULL)) != -1)
switch (opt) {
case 'v':
++s.verbose;
break;
case 'b':
s.pkt_len = strtoul(optarg, 0, 0);
break;
case 'P':
++s.promisc;
break;
case 't':
if (optarg) {
if (!strchr("adzA", optarg[0]))
error(1, 0, "unknown time option '%c'", optarg[0]);
s.time = optarg[0];
} else {
s.time = 'z';
switch (opt) {
case 'v':
++s.verbose;
break;
case 'b':
s.pkt_len = strtoul(optarg, 0, 0);
break;
case 'P':
++s.promisc;
break;
case 't':
if (optarg) {
if (!strchr("adzA", optarg[0]))
err(1, "unknown time option '%c'",
optarg[0]);
s.time = optarg[0];
} else {
s.time = 'z';
}
break;
default:
fputs(help_msg, stderr);
exit(1);
break;
}
break;
default:
fputs(help_msg, stderr);
exit(1);
break;
}
if (argv[optind]) {
optarg = argv[optind];
ret = libj1939_str2addr(optarg, 0, &s.addr);
if (ret < 0) {
error(0, 0, "bad URI %s", optarg);
err(0, "bad URI %s", optarg);
return 1;
}
}
buf = malloc(s.pkt_len);
if (!buf)
error(1, errno, "malloc %u", s.pkt_len);
err(1, "malloc %u", s.pkt_len);
/* setup socket */
sock = socket(PF_CAN, SOCK_DGRAM, CAN_J1939);
if (sock < 0)
error(1, errno, "socket(can, dgram, j1939)");
err(1, "socket(can, dgram, j1939)");
memset(&filt, 0, sizeof(filt));
if (s.addr.can_addr.j1939.name) {
@@ -162,7 +162,7 @@ int main(int argc, char **argv)
filt.addr_mask = ~0;
++filter;
}
if (s.addr.can_addr.j1939.pgn <= 0x3ffff) {
if (s.addr.can_addr.j1939.pgn <= J1939_PGN_MAX) {
filt.pgn = s.addr.can_addr.j1939.pgn;
filt.pgn_mask = ~0;
++filter;
@@ -170,23 +170,23 @@ int main(int argc, char **argv)
if (filter) {
ret = setsockopt(sock, SOL_CAN_J1939, SO_J1939_FILTER, &filt, sizeof(filt));
if (ret < 0)
error(1, errno, "setsockopt filter");
err(1, "setsockopt filter");
}
if (s.promisc) {
ret = setsockopt(sock, SOL_CAN_J1939, SO_J1939_PROMISC, &ival_1, sizeof(ival_1));
if (ret < 0)
error(1, errno, "setsockopt promisc");
err(1, "setsockopt promisc");
}
if (s.time) {
ret = setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP, &ival_1, sizeof(ival_1));
if (ret < 0)
error(1, errno, "setsockopt timestamp");
err(1, "setsockopt timestamp");
}
ret = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &s.pkt_len, sizeof(s.pkt_len));
if (ret < 0)
error(1, errno, "setsockopt rcvbuf %u", s.pkt_len);
err(1, "setsockopt rcvbuf %u", s.pkt_len);
/* bind(): to default, only ifindex is used. */
memset(&src, 0, sizeof(src));
@@ -197,7 +197,7 @@ int main(int argc, char **argv)
src.can_addr.j1939.pgn = J1939_NO_PGN;
ret = bind(sock, (void *)&src, sizeof(src));
if (ret < 0)
error(1, errno, "bind(%s)", argv[1]);
err(1, "bind(%s)", argv[1]);
/* these settings are static and can be held out of the hot path */
iov.iov_base = &buf[0];
@@ -208,7 +208,7 @@ int main(int argc, char **argv)
memset(&tref, 0, sizeof(tref));
if (s.verbose)
error(0, 0, "listening");
err(0, "listening");
while (1) {
/* these settings may be modified by recvmsg() */
iov.iov_len = s.pkt_len;
@@ -221,12 +221,12 @@ int main(int argc, char **argv)
if (ret < 0) {
switch (errno) {
case ENETDOWN:
error(0, errno, "ifindex %i", s.addr.can_ifindex);
err(0, "ifindex %i", s.addr.can_ifindex);
continue;
case EINTR:
continue;
default:
error(1, errno, "recvmsg(ifindex %i)", s.addr.can_ifindex);
err(1, "recvmsg(ifindex %i)", s.addr.can_ifindex);
break;
}
}
@@ -289,7 +289,7 @@ int main(int argc, char **argv)
printf("[%i%s]", len, (msg.msg_flags & MSG_TRUNC) ? "..." : "");
for (j = 0; j < len; ) {
int end = j + 4;
unsigned int end = j + 4;
if (end > len)
end = len;
printf(" ");
+47 -46
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2011 EIA Electronics
*
@@ -9,20 +10,20 @@
* as published by the Free Software Foundation
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <err.h>
#include <getopt.h>
#include <error.h>
#include <poll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "libj1939.h"
@@ -30,9 +31,9 @@
* getopt
*/
static const char help_msg[] =
"jsr: An SAE J1939 send/recv utility" "\n"
"Usage: jsr [OPTION...] SOURCE [DEST]" "\n"
"\n"
"j1939sr: An SAE J1939 send/recv utility" "\n"
"Usage: j1939sr [OPTION...] SOURCE [DEST]" "\n"
"Options:\n"
" -v, --verbose Increase verbosity" "\n"
" -p, --priority=VAL J1939 priority (0..7, default 6)" "\n"
" -S, --serialize Strictly serialize outgoing packets" "\n"
@@ -98,40 +99,40 @@ int main(int argc, char **argv)
#endif
/* argument parsing */
while ((opt = getopt_long(argc, argv, optstring, long_opts, NULL)) != -1)
switch (opt) {
case 'v':
++s.verbose;
break;
case 's':
s.pkt_len = strtoul(optarg, 0, 0);
if (!s.pkt_len)
error(1, EINVAL, "packet size of %s", optarg);
break;
case 'p':
s.priority = strtoul(optarg, 0, 0);
s.defined |= DEF_PRIO;
break;
case 'S':
s.sendflags |= MSG_SYN;
break;
default:
fputs(help_msg, stderr);
exit(1);
break;
}
switch (opt) {
case 'v':
++s.verbose;
break;
case 's':
s.pkt_len = strtoul(optarg, 0, 0);
if (!s.pkt_len)
err(1, "packet size of %s", optarg);
break;
case 'p':
s.priority = strtoul(optarg, 0, 0);
s.defined |= DEF_PRIO;
break;
case 'S':
s.sendflags |= MSG_SYN;
break;
default:
fputs(help_msg, stderr);
exit(1);
break;
}
if (argv[optind]) {
optarg = argv[optind++];
ret = libj1939_str2addr(optarg, 0, &s.src);
if (ret < 0)
error(1, 0, "bad address spec [%s]", optarg);
err(1, "bad address spec [%s]", optarg);
s.defined |= DEF_SRC;
}
if (argv[optind]) {
optarg = argv[optind++];
ret = libj1939_str2addr(optarg, 0, &s.dst);
if (ret < 0)
error(1, 0, "bad address spec [%s]", optarg);
err(1, "bad address spec [%s]", optarg);
s.defined |= DEF_DST;
}
@@ -139,36 +140,36 @@ int main(int argc, char **argv)
struct stat st;
if (fstat(STDIN_FILENO, &st) < 0)
error(1, errno, "stat stdin, could not determine buffer size");
err(1, "stat stdin, could not determine buffer size");
s.pkt_len = st.st_size ?: 1024;
}
/* prepare */
buf = malloc(s.pkt_len);
if (!buf)
error(1, errno, "malloc %u", s.pkt_len);
err(1, "malloc %u", s.pkt_len);
sock = socket(PF_CAN, SOCK_DGRAM, CAN_J1939);
if (sock < 0)
error(1, errno, "socket(can, dgram, j1939)");
err(1, "socket(can, dgram, j1939)");
if (s.defined & DEF_PRIO) {
ret = setsockopt(sock, SOL_CAN_J1939, SO_J1939_SEND_PRIO, &s.priority, sizeof(s.priority));
if (ret < 0)
error(1, errno, "setsockopt priority");
err(1, "setsockopt priority");
}
if (s.defined & DEF_SRC) {
s.src.can_family = AF_CAN;
ret = bind(sock, (void *)&s.src, sizeof(s.src));
if (ret < 0)
error(1, errno, "bind(%s), %i", libj1939_addr2str(&s.src), -errno);
err(1, "bind(%s), %i", libj1939_addr2str(&s.src), -errno);
}
if (s.defined & DEF_DST) {
s.dst.can_family = AF_CAN;
ret = connect(sock, (void *)&s.dst, sizeof(s.dst));
if (ret < 0)
error(1, errno, "connect(%s), %i", libj1939_addr2str(&s.dst), -errno);
err(1, "connect(%s), %i", libj1939_addr2str(&s.dst), -errno);
}
pfd[0].fd = STDIN_FILENO;
@@ -182,27 +183,26 @@ int main(int argc, char **argv)
if (ret < 0) {
if (errno == EINTR)
continue;
error(1, errno, "poll()");
err(1, "poll()");
}
if (pfd[0].revents) {
ret = read(pfd[0].fd, buf, s.pkt_len);
if (ret < 0)
error(1, errno, "read(stdin)");
err(1, "read(stdin)");
if (!ret)
break;
len = ret;
do {
ret = send(pfd[1].fd, buf, len, s.sendflags);
if (ret < 0)
error(errno != ENOBUFS, errno, "write(%s)",
libj1939_addr2str(&s.src));
if (ret < 0 && errno != ENOBUFS)
err(1, "write(%s)", libj1939_addr2str(&s.src));
} while (ret < 0);
}
if (pfd[1].revents) {
ret = read(pfd[1].fd, buf, s.pkt_len);
if (ret < 0) {
ret = errno;
error(0, errno, "read(%s)", libj1939_addr2str(&s.dst));
err(0, "read(%s)", libj1939_addr2str(&s.dst));
switch (ret) {
case EHOSTDOWN:
break;
@@ -210,7 +210,8 @@ int main(int argc, char **argv)
exit(1);
}
} else {
write(STDOUT_FILENO, buf, ret);
if (write(STDOUT_FILENO, buf, ret) < 0)
err(1, "write(stdout)");
}
}
}
+5 -4
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* lib.c - library for command line tools
*
@@ -41,13 +42,13 @@
*
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <sys/socket.h> /* for sa_family_t */
#include <linux/can.h>
#include <linux/can/error.h>
#include <sys/socket.h> /* for sa_family_t */
#include "lib.h"
@@ -582,12 +583,12 @@ void snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *c
if (!sep)
sep = defsep;
for (i = 0; i < ARRAY_SIZE(error_classes); i++) {
for (i = 0; i < (int)ARRAY_SIZE(error_classes); i++) {
mask = 1 << i;
if (class & mask) {
if (classes)
n += snprintf(buf + n, len - n, "%s", sep);
n += snprintf(buf + n, len - n, "%s", error_classes[i]);
n += snprintf(buf + n, len - n, "%s", error_classes[i]);
if (mask == CAN_ERR_LOSTARB)
n += snprintf_error_lostarb(buf + n, len - n,
cf);
+2 -1
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* lib.h - library include for command line tools
*
@@ -96,7 +97,7 @@ int hexstring2data(char *arg, unsigned char *data, int maxdlen);
int parse_canframe(char *cs, struct canfd_frame *cf);
/*
* Transfers a valid ASCII string decribing a CAN frame into struct canfd_frame.
* Transfers a valid ASCII string describing a CAN frame into struct canfd_frame.
*
* CAN 2.0 frames
* - string layout <can_id>#{R{len}|data}
+34 -13
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2011 EIA Electronics
*
@@ -9,17 +10,16 @@
* as published by the Free Software Foundation
*/
#include <string.h>
#include <err.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <inttypes.h>
#include <string.h>
#include <error.h>
#include <unistd.h>
#include <fcntl.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <net/if.h>
@@ -41,7 +41,7 @@ static inline void fetch_names(void)
if (!saved) {
saved = if_nameindex();
if (!saved)
error(1, errno, "if_nameindex()");
err(1, "if_nameindex()");
}
}
@@ -53,7 +53,7 @@ static const char *libj1939_ifnam(int ifindex)
fetch_names();
for (lp = saved; lp->if_index; ++lp) {
if (lp->if_index == ifindex)
if (lp->if_index == (unsigned int)ifindex)
return lp->if_name;
}
if (cached) {
@@ -64,8 +64,8 @@ static const char *libj1939_ifnam(int ifindex)
*/
libj1939_cleanup();
return libj1939_ifnam(ifindex);
} else
return NULL;
}
return NULL;
}
/* retrieve index */
@@ -88,8 +88,29 @@ static int libj1939_ifindex(const char *str)
if (cached) {
libj1939_cleanup();
return libj1939_ifindex(str);
} else
return 0;
}
return 0;
}
void libj1939_parse_canaddr(char *spec, struct sockaddr_can *paddr)
{
char *str;
str = strsep(&spec, ":");
if (strlen(str))
paddr->can_ifindex = if_nametoindex(str);
str = strsep(&spec, ",");
if (str && strlen(str))
paddr->can_addr.j1939.addr = strtoul(str, NULL, 0);
str = strsep(&spec, ",");
if (str && strlen(str))
paddr->can_addr.j1939.pgn = strtoul(str, NULL, 0);
str = strsep(&spec, ",");
if (str && strlen(str))
paddr->can_addr.j1939.name = strtoull(str, NULL, 0);
}
int libj1939_str2addr(const char *str, char **endp, struct sockaddr_can *can)
@@ -162,13 +183,13 @@ const char *libj1939_addr2str(const struct sockaddr_can *can)
}
if (can->can_addr.j1939.name) {
str += sprintf(str, "%016llx", (unsigned long long)can->can_addr.j1939.name);
if (can->can_addr.j1939.pgn == 0x0ee00)
if (can->can_addr.j1939.pgn == J1939_PGN_ADDRESS_CLAIMED)
str += sprintf(str, ".%02x", can->can_addr.j1939.addr);
} else if (can->can_addr.j1939.addr <= 0xfe)
str += sprintf(str, "%02x", can->can_addr.j1939.addr);
else
str += sprintf(str, "-");
if (can->can_addr.j1939.pgn <= 0x3ffff)
if (can->can_addr.j1939.pgn <= J1939_PGN_MAX)
str += sprintf(str, ",%05x", can->can_addr.j1939.pgn);
return buf;
+13
View File
@@ -1,3 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2011 EIA Electronics
*
* Authors:
* Kurt Van Dijck <kurt.van.dijck@eia.be>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the version 2 of the GNU General Public License
* as published by the Free Software Foundation
*/
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/j1939.h>
@@ -9,6 +21,7 @@
extern "C" {
#endif
void libj1939_parse_canaddr(char *spec, struct sockaddr_can *paddr);
extern int libj1939_str2addr(const char *str, char **endp, struct sockaddr_can *can);
extern const char *libj1939_addr2str(const struct sockaddr_can *can);
+137 -35
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* log2asc.c - convert compact CAN frame logfile to ASC logfile
*
@@ -41,15 +42,15 @@
*
*/
#include <libgen.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <libgen.h>
#include <unistd.h>
#include <linux/can.h>
#include <net/if.h>
#include <sys/time.h>
#include <linux/can.h>
#include "lib.h"
@@ -59,24 +60,119 @@ extern int optind, opterr, optopt;
void print_usage(char *prg)
{
fprintf(stderr, "Usage: %s [can-interfaces]\n", prg);
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
fprintf(stderr, " -O <outfile> (default stdout)\n");
fprintf(stderr, " -4 (reduce decimal place to 4 digits)\n");
fprintf(stderr, " -n (set newline to cr/lf - default lf)\n");
fprintf(stderr, "%s - convert compact CAN frame logfile to ASC logfile.\n", prg);
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, " -4 (reduce decimal place to 4 digits)\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)
{
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;
static struct timeval tv, start_tv;
FILE *infile = stdin;
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) {
case 'I':
infile = fopen(optarg, "r");
@@ -98,6 +194,14 @@ int main(int argc, char **argv)
crlf = 1;
break;
case 'f':
fdfmt = 1;
break;
case 'r':
nortrdlc = 1;
break;
case '4':
d4 = 1;
break;
@@ -136,10 +240,17 @@ int main(int argc, char **argv)
if (buf[0] != '(')
continue;
if (sscanf(buf, "(%ld.%ld) %s %s", &tv.tv_sec, &tv.tv_usec,
device, ascframe) != 4) {
fprintf(stderr, "incorrect line format in logfile\n");
return 1;
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) {
fprintf(stderr, "incorrect line format in logfile\n");
return 1;
}
}
if (!start_tv.tv_sec) { /* print banner */
@@ -159,9 +270,14 @@ int main(int argc, char **argv)
}
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;
/* 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_usec = tv.tv_usec - start_tv.tv_usec;
if (tv.tv_usec < 0)
@@ -170,29 +286,15 @@ int main(int argc, char **argv)
tv.tv_sec = tv.tv_usec = 0;
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
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)
fprintf(outfile, "\r");
fprintf(outfile, "\n");
+3 -2
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* log2long.c - convert compact CAN frame representation into user readable
*
@@ -43,15 +44,15 @@
#include <stdio.h>
#include <net/if.h>
#include <linux/can.h>
#include <net/if.h>
#include "lib.h"
#define COMMENTSZ 200
#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];
struct canfd_frame cf;
+55 -34
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* slcan_attach.c - userspace tool for serial line CAN interface driver SLCAN
*
@@ -41,37 +42,38 @@
*
*/
#include <fcntl.h>
#include <getopt.h>
#include <linux/sockios.h>
#include <linux/tty.h>
#include <net/if.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <sys/socket.h>
#include <termios.h>
#include <linux/tty.h>
#include <linux/sockios.h>
#include <unistd.h>
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, "Options: -o (send open command 'O\\r')\n");
fprintf(stderr, " -l (send listen only command 'L\\r', overrides -o)\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, " -s <speed> (set CAN speed 0..8)\n");
fprintf(stderr, " -b <btr> (set bit time register value)\n");
fprintf(stderr, " -d (only detach line discipline)\n");
fprintf(stderr, " -w (attach - wait for keypess - detach)\n");
fprintf(stderr, " -n <name> (assign created netdevice name)\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, " -c (send close command 'C\\r')\n");
fprintf(stderr, " -f (read status flags with 'F\\r' to reset error states)\n");
fprintf(stderr, " -s <speed> (set CAN speed 0..8)\n");
fprintf(stderr, " -b <btr> (set bit time register value)\n");
fprintf(stderr, " -d (only detach line discipline)\n");
fprintf(stderr, " -w (attach - wait for keypess - detach)\n");
fprintf(stderr, " -n <name> (assign created netdevice name)\n");
fprintf(stderr, "\nExamples:\n");
fprintf(stderr, "slcan_attach -w -o -f -s6 -c /dev/ttyS1\n");
fprintf(stderr, "slcan_attach /dev/ttyS1\n");
fprintf(stderr, "slcan_attach -d /dev/ttyS1\n");
fprintf(stderr, "slcan_attach -w -n can15 /dev/ttyS1\n");
fprintf(stderr, "\n");
fprintf(stderr, "slcan_attach -w -o -f -s6 -c /dev/ttyS1\n\n");
fprintf(stderr, "slcan_attach /dev/ttyS1\n\n");
fprintf(stderr, "slcan_attach -d /dev/ttyS1\n\n");
fprintf(stderr, "slcan_attach -w -n can15 /dev/ttyS1\n\n");
exit(1);
}
@@ -87,7 +89,8 @@ int main(int argc, char **argv)
int send_read_status_flags = 0;
char *speed = NULL;
char *btr = NULL;
char buf[IFNAMSIZ+1];
char buf[20];
static struct ifreq ifr;
char *tty;
char *name = NULL;
int opt;
@@ -132,7 +135,7 @@ int main(int argc, char **argv)
case 'n':
name = optarg;
if (strlen(name) > IFNAMSIZ-1)
if (strlen(name) > sizeof(ifr.ifr_newname) - 1)
print_usage(argv[0]);
break;
@@ -157,25 +160,40 @@ int main(int argc, char **argv)
if (speed) {
sprintf(buf, "C\rS%s\r", speed);
write(fd, buf, strlen(buf));
if (write(fd, buf, strlen(buf)) <= 0) {
perror("write");
exit(EXIT_FAILURE);
}
}
if (btr) {
sprintf(buf, "C\rs%s\r", btr);
write(fd, buf, strlen(buf));
if (write(fd, buf, strlen(buf)) <= 0) {
perror("write");
exit(EXIT_FAILURE);
}
}
if (send_read_status_flags) {
sprintf(buf, "F\r");
write(fd, buf, strlen(buf));
if (write(fd, buf, strlen(buf)) <= 0) {
perror("write");
exit(EXIT_FAILURE);
}
}
if (send_listen) {
sprintf(buf, "L\r");
write(fd, buf, strlen(buf));
if (write(fd, buf, strlen(buf)) <= 0) {
perror("write");
exit(EXIT_FAILURE);
}
} else if (send_open) {
sprintf(buf, "O\r");
write(fd, buf, strlen(buf));
if (write(fd, buf, strlen(buf)) <= 0) {
perror("write");
exit(EXIT_FAILURE);
}
}
/* set slcan line discipline on given tty */
@@ -185,16 +203,15 @@ int main(int argc, char **argv)
}
/* retrieve the name of the created CAN netdevice */
if (ioctl (fd, SIOCGIFNAME, buf) < 0) {
if (ioctl (fd, SIOCGIFNAME, ifr.ifr_name) < 0) {
perror("ioctl SIOCGIFNAME");
exit(1);
}
printf("attached tty %s to netdevice %s\n", tty, buf);
printf("attached tty %s to netdevice %s\n", tty, ifr.ifr_name);
/* try to rename the created device if requested */
if (name) {
struct ifreq ifr;
int s = socket(PF_INET, SOCK_DGRAM, 0);
printf("rename netdevice %s to %s ... ", buf, name);
@@ -202,8 +219,9 @@ int main(int argc, char **argv)
if (s < 0)
perror("socket for interface rename");
else {
strncpy (ifr.ifr_name, buf, IFNAMSIZ);
strncpy (ifr.ifr_newname, name, IFNAMSIZ);
/* current slcan%d name is still in ifr.ifr_name */
memset (ifr.ifr_newname, 0, sizeof(ifr.ifr_newname));
strncpy (ifr.ifr_newname, name, sizeof(ifr.ifr_newname) - 1);
if (ioctl(s, SIOCSIFNAME, &ifr) < 0)
printf("failed!\n");
@@ -229,7 +247,10 @@ int main(int argc, char **argv)
if (send_close) {
sprintf(buf, "C\r");
write(fd, buf, strlen(buf));
if (write(fd, buf, strlen(buf)) <= 0) {
perror("write");
exit(EXIT_FAILURE);
}
}
}
+81 -61
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* slcand.c - userspace daemon for serial line CAN interface driver SLCAN
*
@@ -5,9 +6,8 @@
* Copyright (c) 2009 Verari Systems Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* it under the terms of the version 2 of the GNU General Public License
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -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 <stdlib.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 <net/if.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <syslog.h>
#include <termios.h>
#include <linux/tty.h>
#include <linux/sockios.h>
#include <linux/serial.h>
#include <stdarg.h>
#include <unistd.h>
/* Change this to whatever your daemon is called */
#define DAEMON_NAME "slcand"
@@ -72,22 +72,23 @@ static syslog_t syslogger = syslog;
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, "Options: -o (send open command 'O\\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, " -l (send listen only command 'L\\r', overrides -o)\n");
fprintf(stderr, " -s <speed> (set CAN speed 0..8)\n");
fprintf(stderr, " -S <speed> (set UART speed in baud)\n");
fprintf(stderr, " -t <type> (set UART flow control type 'hw' or 'sw')\n");
fprintf(stderr, " -b <btr> (set bit time register value)\n");
fprintf(stderr, " -F (stay in foreground; no daemonize)\n");
fprintf(stderr, " -h (show this help page)\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, " -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, " -s <speed> (set CAN speed 0..8)\n");
fprintf(stderr, " -S <speed> (set UART speed in baud)\n");
fprintf(stderr, " -t <type> (set UART flow control type 'hw' or 'sw')\n");
fprintf(stderr, " -b <btr> (set bit time register value)\n");
fprintf(stderr, " -F (stay in foreground; no daemonize)\n");
fprintf(stderr, " -h (show this help page)\n");
fprintf(stderr, "\nExamples:\n");
fprintf(stderr, "slcand -o -c -f -s6 ttyUSB0\n");
fprintf(stderr, "slcand -o -c -f -s6 ttyUSB0 can0\n");
fprintf(stderr, "slcand -o -c -f -s6 /dev/ttyUSB0\n");
fprintf(stderr, "\n");
fprintf(stderr, "slcand -o -c -f -s6 ttyUSB0\n\n");
fprintf(stderr, "slcand -o -c -f -s6 ttyUSB0 can0\n\n");
fprintf(stderr, "slcand -o -c -f -s6 /dev/ttyUSB0\n\n");
exit(EXIT_FAILURE);
}
@@ -180,7 +181,8 @@ int main(int argc, char *argv[])
char *tty = NULL;
char const *devprefix = "/dev/";
char *name = NULL;
char buf[IFNAMSIZ+1];
char buf[20];
static struct ifreq ifr;
struct termios tios;
speed_t old_ispeed;
speed_t old_ospeed;
@@ -270,6 +272,8 @@ int main(int argc, char *argv[])
print_usage(argv[0]);
name = argv[optind + 1];
if (name && (strlen(name) > sizeof(ifr.ifr_newname) - 1))
print_usage(argv[0]);
/* Prepare the tty device name string */
pch = strstr(tty, devprefix);
@@ -280,23 +284,6 @@ int main(int argc, char *argv[])
syslogger(LOG_INFO, "starting on TTY device %s", ttypath);
/* Daemonize */
if (run_as_daemon) {
if (daemon(0, 0)) {
syslogger(LOG_ERR, "failed to daemonize");
exit(EXIT_FAILURE);
}
}
else {
/* Trap signals that we expect to receive */
signal(SIGINT, child_handler);
signal(SIGTERM, child_handler);
}
/* */
slcand_running = 1;
/* Now we are a daemon -- do the work for which we were paid */
fd = open(ttypath, O_RDWR | O_NONBLOCK | O_NOCTTY);
if (fd < 0) {
syslogger(LOG_NOTICE, "failed to open TTY device %s\n", ttypath);
@@ -305,7 +292,7 @@ int main(int argc, char *argv[])
}
/* Configure baud rate */
memset(&tios, 0, sizeof(struct termios));
memset(&tios, 0, sizeof(tios));
if (tcgetattr(fd, &tios) < 0) {
syslogger(LOG_NOTICE, "failed to get attributes for TTY device %s: %s\n", ttypath, strerror(errno));
exit(EXIT_FAILURE);
@@ -343,25 +330,40 @@ int main(int argc, char *argv[])
if (speed) {
sprintf(buf, "C\rS%s\r", speed);
write(fd, buf, strlen(buf));
if (write(fd, buf, strlen(buf)) <= 0) {
perror("write");
exit(EXIT_FAILURE);
}
}
if (btr) {
sprintf(buf, "C\rs%s\r", btr);
write(fd, buf, strlen(buf));
if (write(fd, buf, strlen(buf)) <= 0) {
perror("write");
exit(EXIT_FAILURE);
}
}
if (send_read_status_flags) {
sprintf(buf, "F\r");
write(fd, buf, strlen(buf));
if (write(fd, buf, strlen(buf)) <= 0) {
perror("write");
exit(EXIT_FAILURE);
}
}
if (send_listen) {
sprintf(buf, "L\r");
write(fd, buf, strlen(buf));
if (write(fd, buf, strlen(buf)) <= 0) {
perror("write");
exit(EXIT_FAILURE);
}
} else if (send_open) {
sprintf(buf, "O\r");
write(fd, buf, strlen(buf));
if (write(fd, buf, strlen(buf)) <= 0) {
perror("write");
exit(EXIT_FAILURE);
}
}
/* set slcan like discipline on given tty */
@@ -371,23 +373,23 @@ int main(int argc, char *argv[])
}
/* retrieve the name of the created CAN netdevice */
if (ioctl(fd, SIOCGIFNAME, buf) < 0) {
if (ioctl(fd, SIOCGIFNAME, ifr.ifr_name) < 0) {
perror("ioctl SIOCGIFNAME");
exit(EXIT_FAILURE);
}
syslogger(LOG_NOTICE, "attached TTY %s to netdevice %s\n", ttypath, buf);
syslogger(LOG_NOTICE, "attached TTY %s to netdevice %s\n", ttypath, ifr.ifr_name);
/* try to rename the created netdevice */
if (name) {
struct ifreq ifr;
int s = socket(PF_INET, SOCK_DGRAM, 0);
if (s < 0)
perror("socket for interface rename");
else {
strncpy(ifr.ifr_name, buf, IFNAMSIZ);
strncpy(ifr.ifr_newname, name, IFNAMSIZ);
/* current slcan%d name is still in ifr.ifr_name */
memset (ifr.ifr_newname, 0, sizeof(ifr.ifr_newname));
strncpy (ifr.ifr_newname, name, sizeof(ifr.ifr_newname) - 1);
if (ioctl(s, SIOCSIFNAME, &ifr) < 0) {
syslogger(LOG_NOTICE, "netdevice %s rename to %s failed\n", buf, name);
@@ -400,6 +402,21 @@ int main(int argc, char *argv[])
}
}
/* Daemonize */
if (run_as_daemon) {
if (daemon(0, 0)) {
syslogger(LOG_ERR, "failed to daemonize");
exit(EXIT_FAILURE);
}
}
else {
/* Trap signals that we expect to receive */
signal(SIGINT, child_handler);
signal(SIGTERM, child_handler);
}
slcand_running = 1;
/* The Big Loop */
while (slcand_running)
sleep(1); /* wait 1 second */
@@ -414,7 +431,10 @@ int main(int argc, char *argv[])
if (send_close) {
sprintf(buf, "C\r");
write(fd, buf, strlen(buf));
if (write(fd, buf, strlen(buf)) <= 0) {
perror("write");
exit(EXIT_FAILURE);
}
}
/* Reset old rates */
+22 -15
View File
@@ -1,13 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* slcanpty.c - creates a pty for applications using the slcan ASCII protocol
* slcanpty: adapter 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)
*
* Copyright (c)2009 Oliver Hartkopp
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* it under the terms of the version 2 of the GNU General Public License
* as published by the Free Software Foundation
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -22,21 +24,24 @@
*
*/
#include <fcntl.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <linux/sockios.h>
/* maximum rx buffer len: extended CAN frame with timestamp */
#define SLC_MTU (sizeof("T1111222281122334455667788EA5F\r")+1)
@@ -74,7 +79,7 @@ int pty2can(int pty, int socket, struct can_filter *fi,
nbytes = read(pty, &buf[rxoffset], sizeof(buf)-rxoffset-1);
if (nbytes <= 0) {
/* nbytes == 0 : no error but pty decriptor has been closed */
/* nbytes == 0 : no error but pty descriptor has been closed */
if (nbytes < 0)
perror("read pty");
@@ -427,16 +432,18 @@ int main(int argc, char **argv)
/* check command line options */
if (argc != 3) {
fprintf(stderr, "\n");
fprintf(stderr, "%s creates a pty for applications using"
" the slcan ASCII protocol and\n", argv[0]);
fprintf(stderr, "%s: adapter for applications using"
" the slcan ASCII protocol.\n", basename(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"
" interface (and vice versa)\n\n");
fprintf(stderr, "Usage: %s <pty> <can interface>\n", argv[0]);
fprintf(stderr, "e.g. '%s /dev/ptyc0 can0' creates"
" /dev/ttyc0 for the slcan application\n", argv[0]);
fprintf(stderr, "Usage: %s <pty> <can interface>\n", basename(argv[0]));
fprintf(stderr, "\nExamples:\n");
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"
" /dev/pts/N\n", argv[0], DEVICE_NAME_PTMX);
" /dev/pts/N\n", basename(argv[0]), DEVICE_NAME_PTMX);
fprintf(stderr, "\n");
return 1;
}
+1
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* Copyright (c) 2002-2007 Volkswagen Group Electronic Research
* All rights reserved.
+136 -89
View File
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2013 EIA Electronics
*
@@ -9,26 +10,26 @@
* as published by the Free Software Foundation
*/
#include <signal.h>
#include <time.h>
#include <inttypes.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <err.h>
#include <getopt.h>
#include <error.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <net/if.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
#include "libj1939.h"
static const char help_msg[] =
"testj1939: demonstrate j1939 use\n"
"Usage: testj1939 FROM TO\n"
"Usage: testj1939 [OPTIONS] FROM TO\n"
" FROM / TO - or [IFACE][:[SA][,[PGN][,NAME]]]\n"
"Options:\n"
" -v Print relevant API calls\n"
@@ -38,57 +39,41 @@ static const char help_msg[] =
" This atually receives packets\n"
" -c Issue connect()\n"
" -p=PRIO Set priority to PRIO\n"
" -P Promiscuous mode. Allow to receive all packets\n"
" -b Do normal bind with SA+1 and rebind with actual SA\n"
" -B Allow to send and receive broadcast packets.\n"
" -o Omit bind\n"
" -n Emit 64bit NAMEs in output\n"
" -w[TIME] Return after TIME (default 1) seconds\n"
"\n"
"Example:\n"
"Examples:\n"
"testj1939 can1 20\n"
"\n"
;
static const char optstring[] = "?vs::rep:cnw::";
static void parse_canaddr(char *spec, struct sockaddr_can *paddr)
{
char *str;
str = strsep(&spec, ":");
if (strlen(str))
paddr->can_ifindex = if_nametoindex(str);
str = strsep(&spec, ",");
if (str && strlen(str))
paddr->can_addr.j1939.addr = strtoul(str, NULL, 0);
str = strsep(&spec, ",");
if (str && strlen(str))
paddr->can_addr.j1939.pgn = strtoul(str, NULL, 0);
str = strsep(&spec, ",");
if (str && strlen(str))
paddr->can_addr.j1939.name = strtoul(str, NULL, 0);
}
static const char optstring[] = "?vbBPos::rep:cnw::";
static void onsigalrm(int sig)
{
error(0, 0, "exit as requested");
err(0, "exit as requested");
exit(0);
}
static void schedule_oneshot_itimer(double delay)
{
struct itimerval it = {};
struct itimerval it = { 0 };
it.it_value.tv_sec = delay;
it.it_value.tv_usec = (long)(delay * 1e6) % 1000000;
if (setitimer(ITIMER_REAL, &it, NULL) < 0)
error(1, errno, "schedule itimer %.3lfs", delay);
err(1, "schedule itimer %.3lfs", delay);
}
/* main */
int main(int argc, char *argv[])
{
int ret, sock, opt, j;
int ret, sock, opt;
unsigned int j;
int verbose = 0;
socklen_t peernamelen;
struct sockaddr_can sockname = {
@@ -108,53 +93,74 @@ int main(int argc, char *argv[])
};
uint8_t dat[128];
int valid_peername = 0;
int todo_send = 0, todo_recv = 0, todo_echo = 0, todo_prio = -1;
int todo_connect = 0, todo_names = 0, todo_wait = 0;
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_broadcast = 0, todo_promisc = 0;
int no_bind = 0;
/* argument parsing */
while ((opt = getopt(argc, argv, optstring)) != -1)
switch (opt) {
case 'v':
verbose = 1;
break;
case 's':
todo_send = strtoul(optarg ?: "8", NULL, 0);
break;
case 'r':
todo_recv = 1;
break;
case 'e':
todo_echo = 1;
break;
case 'p':
todo_prio = strtoul(optarg, NULL, 0);
break;
case 'c':
todo_connect = 1;
break;
case 'n':
todo_names = 1;
break;
case 'w':
schedule_oneshot_itimer(strtod(optarg ?: "1", NULL));
signal(SIGALRM, onsigalrm);
todo_wait = 1;
break;
default:
fputs(help_msg, stderr);
exit(1);
break;
}
switch (opt) {
case 'v':
verbose = 1;
break;
case 's':
todo_send = strtoul(optarg ?: "8", NULL, 0);
if (todo_send > sizeof(dat))
err(1, "Unsupported size. max: %zu",
sizeof(dat));
break;
case 'r':
todo_recv = 1;
break;
case 'e':
todo_echo = 1;
break;
case 'p':
todo_prio = strtoul(optarg, NULL, 0);
break;
case 'P':
todo_promisc = 1;
break;
case 'c':
todo_connect = 1;
break;
case 'n':
todo_names = 1;
break;
case 'b':
todo_rebind = 1;
break;
case 'B':
todo_broadcast = 1;
break;
case 'o':
no_bind = 1;
break;
case 'w':
schedule_oneshot_itimer(strtod(optarg ?: "1", NULL));
signal(SIGALRM, onsigalrm);
todo_wait = 1;
break;
default:
fputs(help_msg, stderr);
exit(1);
break;
}
if (argv[optind]) {
if (strcmp("-", argv[optind]))
parse_canaddr(argv[optind], &sockname);
if (strcmp("-", argv[optind]) != 0)
libj1939_parse_canaddr(argv[optind], &sockname);
++optind;
}
if (todo_rebind)
sockname.can_addr.j1939.addr++;
if (argv[optind]) {
if (strcmp("-", argv[optind])) {
parse_canaddr(argv[optind], &peername);
if (strcmp("-", argv[optind]) != 0) {
libj1939_parse_canaddr(argv[optind], &peername);
valid_peername = 1;
}
++optind;
@@ -165,7 +171,27 @@ int main(int argc, char *argv[])
fprintf(stderr, "- socket(PF_CAN, SOCK_DGRAM, CAN_J1939);\n");
sock = ret = socket(PF_CAN, SOCK_DGRAM, CAN_J1939);
if (ret < 0)
error(1, errno, "socket(j1939)");
err(1, "socket(j1939)");
if (todo_promisc) {
if (verbose)
fprintf(stderr, "- setsockopt(, SOL_SOCKET, SO_J1939_PROMISC, %d, %zd);\n",
todo_promisc, sizeof(todo_promisc));
ret = setsockopt(sock, SOL_CAN_J1939, SO_J1939_PROMISC,
&todo_promisc, sizeof(todo_promisc));
if (ret < 0)
err(1, "setsockopt: filed to set promiscuous mode");
}
if (todo_broadcast) {
if (verbose)
fprintf(stderr, "- setsockopt(, SOL_SOCKET, SO_BROADCAST, %d, %zd);\n",
todo_broadcast, sizeof(todo_broadcast));
ret = setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
&todo_broadcast, sizeof(todo_broadcast));
if (ret < 0)
err(1, "setsockopt: filed to set broadcast");
}
if (todo_prio >= 0) {
if (verbose)
@@ -173,23 +199,37 @@ int main(int argc, char *argv[])
ret = setsockopt(sock, SOL_CAN_J1939, SO_J1939_SEND_PRIO,
&todo_prio, sizeof(todo_prio));
if (ret < 0)
error(1, errno, "set priority %i", todo_prio);
err(1, "set priority %i", todo_prio);
}
if (verbose)
fprintf(stderr, "- bind(, %s, %zi);\n", libj1939_addr2str(&sockname), sizeof(sockname));
ret = bind(sock, (void *)&sockname, sizeof(sockname));
if (ret < 0)
error(1, errno, "bind()");
if (!no_bind) {
if (verbose)
fprintf(stderr, "- bind(, %s, %zi);\n", libj1939_addr2str(&sockname), sizeof(sockname));
ret = bind(sock, (void *)&sockname, sizeof(sockname));
if (ret < 0)
err(1, "bind()");
if (todo_rebind) {
/* rebind with actual SA */
sockname.can_addr.j1939.addr--;
if (verbose)
fprintf(stderr, "- bind(, %s, %zi);\n", libj1939_addr2str(&sockname), sizeof(sockname));
ret = bind(sock, (void *)&sockname, sizeof(sockname));
if (ret < 0)
err(1, "re-bind()");
}
}
if (todo_connect) {
if (!valid_peername)
error(1, 0, "no peername supplied");
err(1, "no peername supplied");
if (verbose)
fprintf(stderr, "- connect(, %s, %zi);\n", libj1939_addr2str(&peername), sizeof(peername));
ret = connect(sock, (void *)&peername, sizeof(peername));
if (ret < 0)
error(1, errno, "connect()");
err(1, "connect()");
}
if (todo_send) {
@@ -218,7 +258,7 @@ int main(int argc, char *argv[])
}
if (ret < 0)
error(1, errno, "sendto");
err(1, "sendto");
}
/* main loop */
@@ -240,7 +280,7 @@ int main(int argc, char *argv[])
fprintf(stderr, "-\t<interrupted>\n");
continue;
}
error(1, errno, "recvfrom()");
err(1, "recvfrom()");
}
if (todo_echo) {
@@ -249,15 +289,22 @@ int main(int argc, char *argv[])
ret = sendto(sock, dat, ret, 0,
(void *)&peername, peernamelen);
if (ret < 0)
error(1, errno, "sendto");
err(1, "sendto");
}
if (todo_recv) {
int i;
if (todo_names && peername.can_addr.j1939.name)
printf("%016llx ", peername.can_addr.j1939.name);
printf("%02x %05x:", peername.can_addr.j1939.addr,
peername.can_addr.j1939.pgn);
for (j = 0; j < ret; ++j)
printf(" %02x", dat[j]);
for (i = 0, j = 0; i < ret; ++i, j++) {
if (j == 8) {
printf("\n%05x ", i);
j = 0;
}
printf(" %02x", dat[i]);
}
printf("\n");
}
}