187 Commits
Author SHA1 Message Date
Oliver Hartkopp cfe41963f3 include: update includes to latest Linux v6.2 upstream
Update includes to support CAN XL and latest CAN netlink features.

Upstream commits:

(1a3e3034c049) "can: canxl: introduce CAN XL data structure"
(061834624c87) "can: set CANFD_FDF flag in all CAN FD frame structures"
(94dfc73e7cf4) "treewide: uapi: Replace zero-length arrays with flexible-array members"
(383f0993fc77) "can: netlink: report the CAN controller mode supported flags"
(d99755f71a80) "can: netlink: add interface for CAN-FD Transmitter Delay Compensation (TDC)"
(63dfe0709643) "can: bittiming: allow TDC{V,O} to be zero and add can_tdc_const::tdc{v,o,f}_min"
(626332696d75) "can: raw: add CAN XL support"

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2023-02-25 14:55:00 +01:00
Ashcon MohseniniaandOliver Hartkopp 999c650e87 slcan: increase BTR char limit to 8 for 32bit BTR
As required by some Atmel MCU SLCAN implementations.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2023-02-23 16:36:33 +01:00
Marc Kleine-BuddeandGitHub 2323d506d6 Merge pull request #406 from marckleinebudde/cangen-fix-usage
cangen: print_usage(): add missing newlines
2023-02-07 19:59:04 +01:00
Marc Kleine-Budde cdc617545f cangen: print_usage(): add missing newlines
Fixes: f55ea38d14 ("cangen: add option for absolute timeouts")
Fixes: c6f2cf7c2f ("cangen: add support for SO_TXTIME")
2023-02-07 19:57:08 +01:00
majkk1andOliver Hartkopp e409aa4c8c cangen: new generation mode - partially randomized payload (-D)
Part of the fixed data payload can be randomized using the 'x' character.
Nibbles marked with 'x' will be randomized.

For example $ vcan0 -D 11xx3344DEADBEEF -L 8:
 -> second byte of the payload will be randomized.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2023-01-28 19:00:57 +01:00
Oliver Hartkopp 3b2248b48e Makefile: add missing defines for CLOCK_TAI, SO_TXTIME and SCM_TXTIME
The commit c6f2cf7c2f ("cangen: add support for SO_TXTIME") relies
on several toolchain features ("CLOCK_TAI", "SO_TXTIME", "SCM_TXTIME")
which are not present in old toolchain.

Add defines to fix compilation on older toolchains.

Reported-by: https://github.com/b-thomson
Link: https://github.com/linux-can/can-utils/issues/398
Fixes: c6f2cf7c2f ("cangen: add support for SO_TXTIME")

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2023-01-28 13:37:49 +01:00
Marc Kleine-BuddeandGitHub fe3717948b Merge pull request #399 from marckleinebudde/fix-old-toolchains
buildsystem: add missing defines for CLOCK_TAI, SO_TXTIME and SCM_TXTIME
2023-01-24 11:54:14 +01:00
Marc Kleine-Budde e898c8a854 buildsystem: add missing defines for CLOCK_TAI, SO_TXTIME and SCM_TXTIME
The commit c6f2cf7c2f ("cangen: add support for SO_TXTIME") relies
on several toolchain features ("CLOCK_TAI", "SO_TXTIME", "SCM_TXTIME")
which are not present in old toolchain.

Add defines to fix compilation on older toolchains.

Reported-by: https://github.com/b-thomson
Link: https://github.com/linux-can/can-utils/issues/398
Fixes: c6f2cf7c2f ("cangen: add support for SO_TXTIME")
2023-01-24 10:04:06 +01:00
Marc Kleine-BuddeandOliver Hartkopp 77ec9b3c2d Revert "cangen: use if_nametoindex() to avoid overflows"
This reverts commit 1f96d674c0.

Link: https://github.com/linux-can/can-utils/pull/396
Link: https://github.com/linux-can/can-utils/commit/1f96d674c0cb7b60ee315981f12a7feb94829697#commitcomment-97455025
2023-01-20 09:58:44 +01:00
Marc Kleine-BuddeandGitHub 5aa72c5e9e Merge pull request #395 from marckleinebudde/mcp251xfd-dump
mcp251xfd dump: add support for dumps created with Linux kernel >= v5.18
2023-01-03 20:45:26 +01:00
Marc Kleine-Budde f3b35e8e80 mcp251xfd-dump: add support for dumps created with Linux kernel >= v5.18 2023-01-03 20:31:54 +01:00
Marc Kleine-Budde b4042d0205 mcp251xfd-dump: add test data 2023-01-03 20:31:54 +01:00
Marc Kleine-Budde 0847fb34b4 mcp251xfd-gen-testdata: add script to generate mcp251xfd-dump data 2023-01-03 20:18:47 +01:00
Marc Kleine-Budde ceb9761544 mcp251xfd-dump: regmap: skip lines that cannot be read 2023-01-03 15:46:07 +01:00
Marc Kleine-Budde 088176e4e0 mcp251xfd-dump: fail if no registers can be read from regmap file 2023-01-03 15:46:07 +01:00
Marc Kleine-BuddeandGitHub aadf98b49b Merge pull request #394 from marckleinebudde/candump-cleanups
candump cleanups
2023-01-03 10:49:40 +01:00
Marc Kleine-Budde 92ae2b0e3d candump: sort getopt() by order of option in usage 2023-01-03 10:37:15 +01:00
Marc Kleine-Budde 306254b950 candump: checkpatch: fix space and newline usage
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2023-01-03 10:37:15 +01:00
Marc Kleine-BuddeandGitHub 34bd45861b Merge pull request #392 from marckleinebudde/cleanups
cleanups
2022-12-19 15:42:42 +01:00
Juergen BorleisandMarc Kleine-Budde 578f42aac8 Buildsystem: provide missing network/CAN related definitions on demand only
Without the corresponding include file, these macros get always defined
locally and thus, shadows the ones from the system. This change ensures,
if the macros are found already defined in the system, then they are used.

Signed-off-by: Juergen Borleis <jbe@pengutronix.de>
2022-12-19 15:31:23 +01:00
Juergen BorleisandMarc Kleine-Budde 3c88cfc1ec Buildsystem: don't define _GNU_SOURCE unconditionally
The "AC_USE_SYSTEM_EXTENSIONS" macros tests it for us.

Signed-off-by: Juergen Borleis <jbe@pengutronix.de>
2022-12-19 15:31:23 +01:00
Juergen BorleisandMarc Kleine-Budde 40819fd038 lib.h: add forgotten declaration
The compiler misses the structure in some source files.

Signed-off-by: Juergen Borleis <jbe@pengutronix.de>
2022-12-19 15:31:23 +01:00
Marc Kleine-BuddeandGitHub 12f1d94856 Merge pull request #391 from marckleinebudde/cansequence
cansequence: do_receive(): improve output in case of packet miss-match
2022-12-19 15:30:42 +01:00
Marc Kleine-Budde 7d375df741 cansequence: do_receive(): improve output in case of packet miss-match 2022-12-19 15:26:28 +01:00
Marc Kleine-BuddeandGitHub 1969f943a2 Merge pull request #390 from marckleinebudde/can-tc-init-etf
can-tc-init-etf: document required kernel config options
2022-12-13 22:39:08 +01:00
Marc Kleine-Budde 1322afa6e4 can-tc-init-etf: document required kernel config options 2022-12-13 22:13:37 +01:00
Marc Kleine-BuddeandGitHub f662b32082 Merge pull request #389 from marckleinebudde/cangen-so_txtime
cangen: add support for SO_TXTIME
2022-12-12 15:08:12 +01:00
Marc Kleine-Budde 5b5f1523c4 can-tc-init-etf: add example script to setup queuing for etf 2022-12-12 13:25:09 +01:00
Marc Kleine-Budde c6f2cf7c2f cangen: add support for SO_TXTIME
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-09 19:47:21 +01:00
Marc Kleine-Budde 9dff4b6393 cangen: do_send_one(): use sendmsg() instead of write()
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-08 10:55:19 +01:00
Marc Kleine-Budde 759524f02c cangen: move write() into separate function
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-08 10:55:18 +01:00
Marc Kleine-Budde f55ea38d14 cangen: add option for absolute timeouts
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-08 10:49:21 +01:00
Marc Kleine-Budde df232c845a cangen: import timespec helper functions
Imported from:

https://github.com/solemnwarning/timespec/commit/0b5b9845ebc932bf7c43b9854b277383909bd057

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-07 16:45:21 +01:00
Marc Kleine-Budde 1ec8eb9ca1 cangen: move sleep directly in font of send()
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-07 16:45:21 +01:00
Marc Kleine-BuddeandGitHub 96309409c2 Merge pull request #388 from marckleinebudde/fix-warnings
fix warnings
2022-12-07 16:40:08 +01:00
Marc Kleine-Budde 7e8cfac0de j1939cat: j1939cat_send(): fix uninitialized variable 2022-12-07 16:35:44 +01:00
Marc Kleine-Budde 0b84a782c2 mcp251xfd-dump: fix comparison of integer expressions of different signedness warning
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-07 16:32:41 +01:00
Marc Kleine-BuddeandGitHub abbd47bd09 Merge pull request #386 from marckleinebudde/cangen-cleanups
cangen cleanups
2022-12-07 15:38:01 +01:00
Marc Kleine-Budde b6a65b8105 cangen: sort getopt() by order of option in usage
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-07 15:28:18 +01:00
Marc Kleine-Budde 99686af630 cangen: print_usage() don't hardcode default burst size
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-07 15:28:18 +01:00
Marc Kleine-Budde 4b6f8d62dd cangen: move scope of variable ret
... so that it can be used in other parts of the main() functions, too.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-07 15:28:18 +01:00
Marc Kleine-Budde 8fb0e954b3 cangen: remove unneeded masking
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-07 15:28:18 +01:00
Marc Kleine-Budde 29b05de39d cangen: mark setsockopt() options as const
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-07 15:28:18 +01:00
Marc Kleine-Budde 1f96d674c0 cangen: use if_nametoindex() to avoid overflows
This patch replaces strcpy() + ioctl() by if_nametoindex() to avoid
overflows caused by long user input.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-07 15:28:18 +01:00
Marc Kleine-Budde 0f7c1aa23a cangen: use consistent indention scheme of 1 space
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-07 15:28:18 +01:00
Marc Kleine-Budde a130ab5e8d cangen: mark functions as static
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-07 15:28:18 +01:00
Marc Kleine-Budde 11a0f19244 cangen: properly initialize struct sockaddr_can addr
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-07 15:28:18 +01:00
Marc Kleine-Budde 8d493edbbe cangen: checkpatch: put braces on all arms of if statement
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-07 15:28:18 +01:00
Marc Kleine-Budde 59c87f149b cangen: checkpatch: don't assign in if statement
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-07 15:28:18 +01:00
Marc Kleine-Budde ad638db75d cangen: checkpatch: remove break after return
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-07 15:28:18 +01:00
Marc Kleine-Budde 1d55d085c9 cangen: checkpatch: fix comment style
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-07 15:28:18 +01:00
Marc Kleine-Budde 77e785b022 cangen: checkpatch: fix space and newline usage
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-07 15:28:18 +01:00
Marc Kleine-Budde 144d77180e cangen: checkpatch: don't split strings over multiple lines
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-07 15:28:18 +01:00
Marc Kleine-Budde 213a814da6 cangen: don't compare floating-point gap with ‘==’
Fixes the following warning:

| cangen.c:524:7: warning: comparing floating-point with ‘==’ or ‘!=’ is unsafe [-Wfloat-equal]
|   524 |   if (gap && burst_sent_count >= burst_count) /* gap == 0 => performance test :-] */
|       |       ^~~

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-07 15:26:42 +01:00
Marc Kleine-BuddeandGitHub a18337b102 Merge pull request #387 from marckleinebudde/can-calc-bit-timing
can-calc-bit-timing: fix various compiler warnings
2022-12-07 15:22:51 +01:00
Marc Kleine-Budde 0b3112edf2 can-calc-bit-timing: remove const from printf_btr functions to silence warning on clang
Fixes: 9b63929974 ("can-calc-bit-timing: mark several structs and members as const")
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-07 15:08:59 +01:00
Marc Kleine-Budde 74897b69c3 can-calc-bit-timing: silence "comparison of integer expressions of different signedness" warning
Silence the "comparison of integer expressions of different
signedness" warning. We want to compile the code as is from the
kernel, including bugs.

| calc-bit-timing/can-calc-bit-timing-v2_6_31.c: In function ‘can_update_spt_v2_6_31’:
| calc-bit-timing/can-calc-bit-timing-v2_6_31.c:51:13: warning: comparison of integer expressions of different signedness: ‘int’ and ‘__u32’ {aka ‘const unsigned int’} [-Wsign-compare]

Fixes: 18eb0ab784 ("can-calc-bit-timing: import bit timing calculation algorithm from v4.8")
Fixes: b777ce2e6d ("can-calc-bit-timing: import bit timing calculation algorithm from v3.18")
Fixes: c1f5dc53ec ("can-calc-bit-timing: import bit timing calculation algorithm from v2.6.31")
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-12-07 14:50:02 +01:00
Marc Kleine-Budde 9177294093 Merge patch series "can-utils-dev: a set of update and cleanup patches"
Vincent Mailhol <mailhol.vincent@wanadoo.fr> says:

This series contain cleanup patches and update of header files. There
is no real relation between each patch (aside of 2/6 and 3/6 which
form a pair) so I will end the cover letter here and let you refer to
the short description.

* Changelog *

v2 -> v3:

  * reorder the patches so that related changes are next to each
    other (especially patch 2/6 and 3/6).

  * patch 2/6: new patch to update include/linux/can/error.h with the
    latest hearder from Linux 6.0.0.

  * patch 3/6: do not use an #ifdef anymore and make sure that the
    code still work if run on old kernel version lower than 6.0.0.

  * patch 6/6: rewrite commit description to point out that there is a
    local copy of the linux headers under include/linux/.

v1 -> v2:

  * patch 2/5: add a note in commit message to explain that slcanpty.c
    debug is deactivated by default.

  * patch 2/5: make the compiler check the pr_debug() syntax even if
    debug is off.

  * reorder the patches so that the lib.c and the candump.c patches
    are next to each other in the series.

Link: https://lore.kernel.org/all/20221114163848.3398-1-mailhol.vincent@wanadoo.fr
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-11-15 10:14:47 +01:00
Vincent MailholandMarc Kleine-Budde 4764212483 candump: use linux/net_tstamp.h instead of redefining values ourselves
The project contains a local copy of the timestamp header at
include/linux/net_tstamp.h. However, candump.c redefines the
net_tstamp.h values instead of relying on the header.

Replace these by a "include <linux/net_tstamp.h>".

Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://lore.kernel.org/all/20221114163848.3398-7-mailhol.vincent@wanadoo.fr
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-11-15 09:49:52 +01:00
Vincent MailholandMarc Kleine-Budde 8e45fc5158 candump: add global variable progname
Instead of using argv[0] several time, make the progname a global
variable.

Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://lore.kernel.org/all/20221114163848.3398-6-mailhol.vincent@wanadoo.fr
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-11-15 09:49:52 +01:00
Vincent MailholandMarc Kleine-Budde 0cfd56d613 lib: add pr_debug() macro
Add the pr_debug() macro so that:

  #ifdef DEBUG
  	printf("foo");
  #endif

can be replaced by:

  	pr_debug("foo");

Apply the pr_debug() macro wherever relevant.

Currently, there is no consensus whether debug messages should be
printed on stdout or stderr. Most of the modules: canbusload.c,
candump.c and canlogserver.c use stdout but
mcp251xfd/mcp251xfd-dev-coredump.c uses stderr. Harmonize the behavior
by following the major trend and make
mcp251xfd/mcp251xfd-dev-coredump.c also output to stdout.

slcanpty.c does a #define DEBUG, meaning that debug is always turned
on for this file. Remove this and make debug an option like every
other files.

Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://lore.kernel.org/all/20221114163848.3398-5-mailhol.vincent@wanadoo.fr
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-11-15 09:49:52 +01:00
Vincent MailholandMarc Kleine-Budde 21fb43532e lib: snprintf_can_error_frame: print counter errors if CAN_ERR_CNT is set
Since version 6.0.0 (specifically [1]), the kernel has a new flag:
CAN_ERR_CNT to notify whether or not the error counter is set. Use
this to decide whether on not the error-counter-tx-rx should be
printed.

This way, when a driver set data[6] and data[7] to zero, it is
possible to differentiate whether the error counter is not available
or if the drivers simply reported both counters to be zero.

For interoperability reasons, continue to check data[6] and data[7]
against zero so that the code still works with the old behavior if
run on a kernel version lower than 6.0.0.

[1] commit 3e5c291c7942 ("can: add CAN_ERR_CNT flag to notify
    availability of error counter")
Link: https://git.kernel.org/torvalds/linux/c/3e5c291c7942

Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://lore.kernel.org/all/20221114163848.3398-4-mailhol.vincent@wanadoo.fr
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-11-15 09:44:51 +01:00
Vincent MailholandMarc Kleine-Budde f3ce3efe66 include: update linux/can/error.h
Update the linux/can/error.h hearder to incorporate the changes made
in Linux 6.0.0. Namely:

  - commit 3e5c291c7942 ("can: add CAN_ERR_CNT flag to notify
    availability of error counter")
    Link: https://git.kernel.org/torvalds/linux/c/3e5c291c7942

  - commit 3f9c26210cf8 ("can: error: add definitions for the
    different CAN error thresholds")
    Link: https://git.kernel.org/torvalds/linux/c/3f9c26210cf8

Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://lore.kernel.org/all/20221114163848.3398-3-mailhol.vincent@wanadoo.fr
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-11-15 09:44:51 +01:00
Vincent MailholandMarc Kleine-Budde 4c9f046615 slcanpty: remove redundant asc2nibble()
asc2nibble() is already defined in lib.h. Include lib.h in slcnpty.c
so that asc2nibble() does not need to be redefined a second time and
adjust the Makefile accordingly.

Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://lore.kernel.org/all/20221114163848.3398-2-mailhol.vincent@wanadoo.fr
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-11-15 09:44:51 +01:00
Marc Kleine-BuddeandGitHub 71a0156bd5 Merge pull request #380 from marckleinebudde/fix-fname-scope
candump: main(): fix scope of fname
2022-09-29 12:50:05 +02:00
Marc Kleine-Budde e54d677999 candump: main(): fix scope of fname
Reported-by: https://github.com/HBLocker
Link: https://github.com/linux-can/can-utils/issues/379
2022-09-29 12:47:17 +02:00
Marc Kleine-BuddeandGitHub 2b3b5c498f Merge pull request #378 from RICCIARDI-Adrien/canfdtest_add_extended_frame_format_support
canfdtest: Add extended frame format support
2022-09-09 11:28:19 +02:00
RICCIARDI-Adrien 8e66a0bae3 canfdtest: Add extended frame format support
Added the '-e' command line option to enable 29-bit CAN ID.

Signed-off-by: RICCIARDI-Adrien <adrien.ricciardi@hotmail.fr>
2022-09-09 11:01:43 +02:00
Marc Kleine-BuddeandGitHub e602e391a5 Merge pull request #376 from marckleinebudde/fix-candump
candump: fix HW timestamps + dropcount
2022-08-28 00:21:27 +02:00
Marc Kleine-Budde 2b5e93744b candump: reserve enough space for ctrlmsg
The ctrlmsg must be large enough to contains 3 elements of various
sizes, not a single element of the sum of the size.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-08-27 23:26:39 +02:00
Marc Kleine-Budde 0d26ba9ea3 candump: print number of dropped frames as unsigned values
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-08-27 23:25:18 +02:00
Marc Kleine-BuddeandGitHub 5736818292 Merge pull request #375 from jhofstee/fix_snprintf_error_data
lib: fix seperator in snprintf_error_data
2022-08-17 17:11:34 +02:00
Jeroen Hofstee 3bb412e072 lib: fix seperator in snprintf_error_data
When multiple error flags are set, snprintf_error_data created a comma
seperated textual presentation of it. Commit ef853f5553 ("added return value
check of snprintf to prevent possible buffer overflows detected by CodeQL")
removed the increment of count, so the delimiter is no longer added. Fix this
by incrementing count again.

Fixes: Commit ef853f5553 ("added return value check of snprintf to prevent possible buffer overflows detected by CodeQL")
Signed-off-by: Jeroen Hofstee <jhofstee@victronenergy.com>
2022-08-17 16:57:26 +02:00
Marc Kleine-BuddeandGitHub f020f563e7 Merge pull request #374 from marckleinebudde/fix-android
Android.mk: fix compilation of can-calc-bit-timing
2022-08-17 11:54:50 +02:00
Marc Kleine-Budde e0945d867e CMakeLists: fix compilation of can-calc-bit-timing
Fixes: 9c38c16437 ("can-calc-bit-timing: move into subdir")
Reported-by: Tompee Balauag <tompee26@gmail.com>
Link: https://github.com/linux-can/can-utils/issues/373
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-08-17 11:39:16 +02:00
Marc Kleine-Budde f81ce85730 Android.mk: fix compilation of can-calc-bit-timing
Fixes: 9c38c16437 ("can-calc-bit-timing: move into subdir")
Reported-by: Tompee Balauag <tompee26@gmail.com>
Link: https://github.com/linux-can/can-utils/issues/373
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-08-17 09:07:01 +02:00
Marc Kleine-BuddeandGitHub a44238c9e2 Merge pull request #372 from marckleinebudde/calc-bit-timing
improve can-calc-bittiming
2022-08-12 15:16:02 +02:00
Marc Kleine-Budde 7e2010a1c0 can-calc-bit-timing: import bit timing calculation algorithm from v5.19
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-08-11 22:42:16 +02:00
Marc Kleine-Budde 0654d4e711 can-calc-bit-timing: import bit timing calculation algorithm from v5.16
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-08-11 22:42:16 +02:00
Marc Kleine-Budde 18eb0ab784 can-calc-bit-timing: import bit timing calculation algorithm from v4.8
The bit timing algorithm is not identical with the referenced commit.
So re-import from that commit.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-08-11 22:25:51 +02:00
Marc Kleine-Budde b777ce2e6d can-calc-bit-timing: import bit timing calculation algorithm from v3.18
add missing can_fixup_bittiming()

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-08-11 22:25:16 +02:00
Marc Kleine-Budde c1f5dc53ec can-calc-bit-timing: import bit timing calculation algorithm from v2.6.31
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-08-11 22:24:43 +02:00
Marc Kleine-Budde ee2f48f33b can-calc-bit-timing: move algorithms into separate files
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-08-11 21:47:47 +02:00
Marc Kleine-Budde a7062893da can-calc-bit-timing: add can_fixup_bittiming to alg
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-08-11 21:45:50 +02:00
Marc Kleine-Budde cfc3030080 can-calc-bit-timing: prepare for more algos
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-08-11 21:25:40 +02:00
Marc Kleine-Budde 9c38c16437 can-calc-bit-timing: move into subdir
The source file will be split into several files in the next patches.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-08-11 20:34:40 +02:00
Marc Kleine-Budde 258f357814 can-calc-bit-timing: add information if printing data bit timing table
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-08-11 20:34:40 +02:00
Marc Kleine-Budde ab2b11d9a8 can-calc-bit-timing: add new ref_clk to xilinx_can_fd2
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-08-11 20:34:40 +02:00
Marc Kleine-Budde 710fc99961 can-calc-bit-timing: add new ref_clk to mcp2515
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-08-11 20:34:40 +02:00
Marc Kleine-Budde 104e3f97a0 can-calc-bit-timing: add new ref_clk to mcan
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-08-11 20:34:39 +02:00
Marc Kleine-Budde 2b2d38d06b can-calc-bit-timing: fix indention
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-08-11 16:35:59 +02:00
Marc Kleine-Budde 75291c2a88 can-calc-bit-timing: common_bitrates: add more bitrates
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-08-11 16:35:59 +02:00
Marc Kleine-BuddeandGitHub cad1cecf1c Merge pull request #370 from weichslgartner/master
fix for issue #369
2022-07-04 14:43:57 +02:00
weichslgartner da0326ffc6 fix for issue #369
adding cast preventing int/unsigned comparison (-Wsign-compare warning in lib.c)
2022-06-30 18:40:07 +02:00
Marc Kleine-BuddeandGitHub cfe13a4c7d Merge pull request #368 from RICCIARDI-Adrien/canfdtest_add_message_length_support
canfdtest: Add message length support
2022-06-28 10:50:52 +02:00
RICCIARDI-Adrien b8af5a6031 canfdtest: Add message length support
Added the '-s' command line option to set the frame payload length in bytes.

Signed-off-by: RICCIARDI-Adrien <adrien.ricciardi@hotmail.fr>
2022-06-27 23:49:02 +02:00
Marc Kleine-BuddeandGitHub 5e06623b3d Merge pull request #366 from RICCIARDI-Adrien/canfdtest_add_bit_rate_switch_support
canfdtest: Add CAN FD Bit Rate Switch support
2022-06-22 11:34:09 +02:00
RICCIARDI-Adrien 6d3bf51e0a canfdtest: Add CAN FD Bit Rate Switch support
Added the '-b' command line option, to be used in conjunction with the '-d'
option that enables CAN FD, to set the BRS bit in a CAN FD frame. When
enabled, the data part of the CAN FD frame is transmitted at a higher speed.
All remaining parts of the CAN FD frame use the classic CAN speed.

Signed-off-by: RICCIARDI-Adrien <adrien.ricciardi@hotmail.fr>
2022-06-22 10:50:12 +02:00
Marc Kleine-BuddeandGitHub 2b0ed067dd Merge pull request #321 from weichslgartner/master
Fixed some undefined behavior and added CodeQL workflow
2022-06-20 19:40:36 +02:00
weichslgartner ef853f5553 added return value check of snprintf to prevent possible buffer overflows detected by CodeQL 2022-06-20 19:22:11 +02:00
weichslgartner eb2b38790a fixes undefined behavior in parse_canframe (lib.c:187) by chaning tmp to
canid_t

Issue:
mkdir build && cd build
CC=clang cmake -DCMAKE_C_FLAGS="-fsanitize=address,undefined"
-DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address,undefined" .. && cmake
--build .

 echo "(0.0) can1 ffffffff#00000000" | ./log2long
can-utils/lib.c:187:23: runtime error: left shift of 15 by 28 places
cannot be represented in type 'int'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior
/can-utils/lib.c:187:23 in
(0.0)  can1  3FFFFFFF
2022-06-20 19:11:00 +02:00
Marc Kleine-BuddeandGitHub bace2e7d73 Merge pull request #365 from RICCIARDI-Adrien/canfdtest_add_can_fd_support
canfdtest: Add CAN FD support
2022-06-20 18:30:14 +02:00
RICCIARDI-Adrien d3bb67136f canfdtest: Add CAN FD support
Add the '-d' command line option that allow to transmit CAN FD frames instead
of CAN 2.0 frames. The frames content is the same.

This allows to stress test the flexible data rate part of a CAN FD network.

Signed-off-by: RICCIARDI-Adrien <adrien.ricciardi@hotmail.fr>
2022-06-20 18:13:18 +02:00
weichslgartner 34732eddeb fixed signed integer overflow in asc2log.c:100
Issue:
echo "0.0000 0  Rx   d 8 8D 00 10 01 00 82 01 00
      0.200000000000000000 0- 0000  Rx   d 8 8D 00 10 01 00 82 01 00" |
./asc2log

can-utils/asc2log.c:100:20: runtime error: signed integer overflow:
200000000000000000 * 100 cannot be represented in type 'long'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior asc2log.c:100:20
2022-06-13 17:42:33 +02:00
weichslgartner 2b0ef5c330 Create codeql-analysis.yml 2022-06-13 17:42:33 +02:00
Oliver Hartkopp 6e7f845a68 isotpsend: add support for transmission without flow control
Usually the ISO 15765-2 protocol is a point-to-point protocol to transfer
segmented PDUs to a dedicated receiver. This receiver sends a flow control
message to specify protocol options and timings (e.g. block size / STmin).

The so called functional addressing communication allows a 1:N
communication but is limited to a single frame length.

The new CAN_ISOTP_CF_BROADCAST flag introduced in Linux 5.19 allows an
unconfirmed 1:N communication with PDU lengths that would not fit into a
single frame. This feature is not covered by the ISO 15765-2 standard.

The isotpsend tool gets a new option '-C' to enable this unconfirmed 1:N
communication by setting the CAN_ISOTP_CF_BROADCAST flag.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2022-05-13 20:00:45 +02:00
Oliver Hartkopp d320a4a871 asc2log: reduce code duplication
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2022-05-01 13:57:25 +02:00
Oliver Hartkopp 81e76a7a0d log asc converter: support len8_dlc for Classical CAN frames part 2
In commit 6799180bd0 ("log asc converter: support len8_dlc for Classical
CAN frames") the len8_dlc support was accidentally only implemented for
the new CANFD asc format. This patch adds len8_dlc support for the 'old'
Classical CAN asc format which in fact always supported len8_dlc.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2022-05-01 13:47:57 +02:00
Oliver Hartkopp 2bdb93924e asc2log: make sure we have read the dlc value with sscanf()
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2022-05-01 13:02:08 +02:00
Oliver Hartkopp afc6a324da asc2log: move check for error frames
We need to check for different sscanf() failures and the number of read
items in the data frames. So move the simple check to the beginning.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2022-05-01 12:55:49 +02:00
Marc Kleine-BuddeandGitHub 901c9e519d Merge pull request #354 from philschenker/master
Return -1 Exit-Code if compare_frame fails
2022-04-12 17:21:43 +02:00
Philippe Schenker 26842295b8 canfdtest: make use of return value of check_frame
check_frame has a return value. Make use of this in can_echo_dut which
then is evaluated and returned thereof in main()

Signed-off-by: Philippe Schenker <philippe.schenker@toradex.com>
2022-04-12 17:18:22 +02:00
Philippe Schenker 24de626f33 canfdtest: return -1 if compare_frame fails
Do report errors from function compare_frame also on the exit-code.

Signed-off-by: Philippe Schenker <philippe.schenker@toradex.com>
2022-04-12 17:10:58 +02:00
Oliver Hartkopp c70d0a8e61 candump: handle individual logfile name for stdout
Since commit ad250a68dc ("candump: add option to define individual
filename for logfile") the option "-f <fname>" allows to define an
individual filename for a logfile.

Usually the "-" is used as filename to represent stdout or stdin on
Linux/Posix systems to be able to concatenate several applications via
pipes. This patch handles this special case by detecting the filename
"-" to print the logfile format on stdout instead of creating a logfile
with the name "-".

Fixes: ad250a68dc ("candump: add option to define individual filename for logfile")
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2022-03-25 15:15:57 +01:00
Marc Kleine-BuddeandGitHub aa3f029925 Merge pull request #351 from hartkopp/isotp-updates
isotp: support Linux 5.18 features
2022-03-14 20:47:09 +01:00
Oliver Hartkopp dfb607c807 remove obsolete char pointer casts
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2022-03-14 18:21:45 +01:00
Oliver Hartkopp 84d3294132 isotp: support Linux 5.18 features
- update isotp.h include file
- update maximum PDU (buffer) size to 64kByte buffer
- support setting of N_As (frame_txtime) to zero

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2022-03-12 18:09:48 +01:00
Oliver Hartkopp 5e0895981b candump: fix accidentally disabled traffic timeout feature
With the option '-T <msecs>' candump terminates after getting no CAN traffic
for a specific time. With the introduction of epoll_wait() this feature
has been accidentally disabled.

This patch adds an extra check to detect the timeout again.

Fixes: 639498bc80 ("candump: use epoll_wait() instead of select()")
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2022-03-07 10:32:41 +01:00
Oliver Hartkopp ad250a68dc candump: add option to define individual filename for logfile
Link: https://github.com/linux-can/can-utils/pull/345
Suggested-by: https://github.com/xR3b0rn
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2022-02-16 11:46:46 +01:00
Marc Kleine-BuddeandGitHub ec6a573de1 Merge pull request #342 from hartkopp/isotpsend
isotpsend: add new options to generate PDU traffic load
2022-02-10 09:29:19 +01:00
Oliver Hartkopp acec220189 isotpsend: add new options to generate PDU traffic load
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2022-02-09 18:34:09 +01:00
Marc Kleine-BuddeandGitHub b38d2639ba Merge pull request #341 from marckleinebudde/mcp251xfd-dump
mcp251xfd-dump: add dump for IOCON register
2022-02-09 08:36:25 +01:00
Marc Kleine-Budde 0ccc3fed91 mcp251xfd-dump: add dump for IOCON register 2022-02-09 08:29:53 +01:00
Marc Kleine-BuddeandGitHub 9f9f2ff721 Merge pull request #340 from marckleinebudde/fix-typo
cansniffer: main(): fix typo comand -> command
2022-02-01 16:14:22 +01:00
Marc Kleine-Budde 00fbc5d536 cansniffer: main(): fix typo comand -> command
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-02-01 16:13:20 +01:00
Marc Kleine-BuddeandGitHub 2758f8eb62 Merge pull request #339 from jaiqc/master
closes #master: Fixed typo error in isodump
2022-02-01 16:07:52 +01:00
Jayachandran Dharuman 2ac24b86fd closes #master: Fixed typo erros in slcan and testj1939 2022-02-01 19:55:27 +05:30
Jayachandran Dharuman a4d2ee75bc closes #master: Fixed typo error in isodump 2022-02-01 19:38:41 +05:30
Marc Kleine-BuddeandGitHub 4984eb702e Merge pull request #333 from marckleinebudde/bittiming-canfd-support
can-calc-bit-timing: add CAN-FD support
2022-01-27 16:06:40 +01:00
Marc Kleine-BuddeandGitHub 4bd649d73a Merge pull request #336 from weidmueller/feature/fix-poll-function-calls
Fix error detection of poll function calls
2022-01-27 16:05:50 +01:00
Stefan Herbrechtsmeier 25de6276e8 j1939cat: fix error detection of poll function call
The poll function return -1 on error and set errno to indicate the
error.

Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
2022-01-27 15:53:10 +01:00
Stefan Herbrechtsmeier 7af4264a13 cansequence: exit program with failure in case of poll timeout
The poll function returns 0 to indicate a call timed out.

Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
2022-01-27 15:53:10 +01:00
Stefan Herbrechtsmeier 3342eb42e7 cangen: Do not treat -EINTR as error 2022-01-27 15:53:10 +01:00
Stefan Herbrechtsmeier c142ca63c9 cangen: exit program with failure in case of poll timeout
The poll function returns 0 to indicate a call timed out.

Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
2022-01-27 14:31:37 +01:00
Marc Kleine-BuddeandGitHub 4858b2b307 Merge pull request #334 from hartkopp/cansniffer-fd
cansniffer: add CAN FD support
2022-01-22 17:11:08 +01:00
Oliver Hartkopp 8ffcc187e9 cansniffer: make ASCII output switchable in CAN FD mode
In CAN FD mode the length of the output line becomes very long.
Therefore disable the ASCII output in CAN FD mode by default but
make it switchable with a new '@' command in interactive input mode.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2022-01-22 14:51:20 +01:00
Oliver Hartkopp c3129b678a cansniffer: add CAN FD support
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2022-01-22 14:48:14 +01:00
Oliver Hartkopp 540dcaa821 cansniffer: convert to struct canfd_frame for FD support
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2022-01-22 13:50:03 +01:00
Oliver Hartkopp fb186ed6c8 cansniffer: add error handling for read/write of sniffsets
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2022-01-22 13:49:23 +01:00
Marc Kleine-Budde 66631a3e23 can-calc-bit-timing: add more bittiming constants and sort them
Import all bit timing constants from the kernel (v5.16-rc1) and sort
them by the occurrence in drivers/net/can/Makefile.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-01-19 21:59:58 +01:00
Marc Kleine-Budde e7b5920b10 can-calc-bit-timing: beautify btr register printing
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-01-19 21:39:30 +01:00
Marc Kleine-Budde 2636640aa7 can-calc-bit-timing: import bit timing calculation algorithm from v3.18
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-01-19 21:39:30 +01:00
Marc Kleine-Budde f42e968bcf can-calc-bit-timing: add support for additional bit timing calculation algorithms
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-01-19 21:39:30 +01:00
Marc Kleine-Budde f9c9f6841b can-calc-bit-timing: document kernel commit of current bit timing calculation algorithm
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-01-19 07:21:38 +01:00
Marc Kleine-Budde 8d01589500 can-calc-bit-timing: move struct definitions
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-01-19 07:21:38 +01:00
Marc Kleine-Budde 046d9f88ee can-calc-bit-timing: add option to specify explicit data bit timing 2022-01-19 07:21:38 +01:00
Marc Kleine-Budde 36d76ba07a can-calc-bit-timing: add support for calculation of CAN-FD bit timings
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-01-19 07:21:38 +01:00
Marc Kleine-Budde 04123b3b36 can-calc-bit-timing: print_bittiming(): skip bit timing without ref clock
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-01-19 07:21:38 +01:00
Marc Kleine-Budde 2829512f9b can-calc-bit-timing: add nop printf_btr
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-01-16 12:25:01 +01:00
Marc Kleine-Budde 7ec433f6a6 can-calc-bit-timing: prepare for different can_bittiming (i.e. CAN-FD)
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-01-16 12:24:42 +01:00
Marc Kleine-Budde 7bc81678bb can-calc-bit-timing: rename rate -> bitrate
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-01-16 12:24:42 +01:00
Marc Kleine-Budde 927f70e588 can-calc-bit-timing: rename spt -> sample_point
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-01-16 12:24:42 +01:00
Marc Kleine-Budde 9b63929974 can-calc-bit-timing: mark several structs and members as const
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-01-16 12:24:04 +01:00
Marc Kleine-Budde 258ea5a9ba can-calc-bit-timing: fix whitespace
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-01-15 15:10:19 +01:00
Marc Kleine-BuddeandGitHub 4c07a11f81 Merge pull request #331 from marckleinebudde/fix-typo
libj1939.h: fix typo
2022-01-03 10:58:52 +01:00
Marc Kleine-Budde 3394e1fa18 libj1939.h: fix typo
Fixes: e370ad5256 ("testj1939: fix 64-bit types for some platforms")
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-01-03 10:58:05 +01:00
Marc Kleine-BuddeandGitHub 9e5b6266b1 Merge pull request #330 from marckleinebudde/fix-types
testj1939: fix 64-bit types for some platforms
2022-01-03 10:47:39 +01:00
Rosen PenevandMarc Kleine-Budde e370ad5256 testj1939: fix 64-bit types for some platforms
Revert commit that introduced PRIx64 to print an __u64, and added
define to get the same types on all platforms.

With __SANE_USERSPACE_TYPES__ the Linux headers use an unsigned long
long for __u64 on all platforms, especially MIPS64.

Fixes: eb9cfac954 ("use PRIx64")
Signed-off-by: Rosen Penev <rosenp@gmail.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2022-01-03 10:44:29 +01:00
Marc Kleine-BuddeandGitHub fd1d61490c Merge pull request #328 from marckleinebudde/fix-musl
CMakeLists: unconditionally define _GNU_SOURCE
2021-12-30 13:00:59 +01:00
Marc Kleine-Budde da642181a9 CMakeLists: unconditionally define _GNU_SOURCE
This fixes compilation on musl libc.

Link: https://github.com/linux-can/can-utils/pull/326
Reported-by: Rosen Penev <rosenp@gmail.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2021-12-30 12:57:12 +01:00
Marc Kleine-BuddeandGitHub 6bd7ced052 Merge pull request #325 from neheb/patch-1
mcp251xfd: add missing libgen.h header
2021-12-16 10:05:09 +01:00
Marc Kleine-BuddeandGitHub 9ca68a12c7 Merge pull request #327 from neheb/patch-3
use PRIx64
2021-12-16 10:04:04 +01:00
Rosen PenevandGitHub eb9cfac954 use PRIx64
This is the proper specifier for uint64_t.
2021-12-15 18:08:13 -08:00
Rosen PenevandGitHub 7dd714907b mcp251xfd: add missing libgen.h header
Needed for the basename() function under musl.
2021-12-15 18:00:39 -08:00
Oliver Hartkopp a705182b28 candump: trivial typo exchange sentence point with closing bracket
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2021-11-28 20:14:43 +01:00
Oliver Hartkopp 0d84033fa4 canplayer: introduce option to limit the number of processed frames
Analogue to the '-n <count>' option to limit the number of processed CAN
frames in candump and cangen this option makes sense in canplayer too.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2021-10-30 13:02:42 +02:00
Marc Kleine-BuddeandGitHub ab9bd4f287 Merge pull request #318 from jgressma/feat/canfdtest-custom-can-ids-squashed
canfdtest: enables program use alongside existing CAN bus traffic
2021-10-25 15:33:09 +02:00
Jean Gressmann 2dde06801a canfdtest: adds support for custom CAN IDs
This change enables the use of this app alongside the traffic
typically found on a CAN bus.
2021-10-25 11:20:58 +02:00
Marc Kleine-BuddeandGitHub 607b643e0f Merge pull request #319 from marckleinebudde/fix-j1939cat
j1939cat: properly fix printf format string to work both on 32 and 64 bit systems
2021-10-21 11:24:12 +02:00
Marc Kleine-Budde eb0eb78896 j1939cat: properly fix printf format string to work both on 32 and 64 bit systems
Fixes: 7b8457ce9f ("j1939cat: fix long long unsigned int warning in x_name printf")
Fixes: cc155d2f63 ("j1939cat: make use of new RX UAPI")
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2021-10-21 11:20:12 +02:00
Oliver Hartkopp 0edab8a402 cangen: improve help text to point out decimal places for the gap value
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2021-10-20 06:12:27 +02:00
Oliver Hartkopp 622fcbb9b3 Makefile: remove obsolete requirements for lib.h
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2021-10-19 08:57:22 +02:00
Marc Kleine-BuddeandGitHub 02e8b1ff39 Merge pull request #316 from Rubusch/lothar/cansniffer
cansniffer: fix detection of invalid provided CAN interface, refacs
2021-10-19 08:43:20 +02:00
Lothar Rubusch 9fd2b2e617 Makefile: clean mcp251xfd/*.o
make distclean depend on clean target in Makefile

Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
2021-10-18 22:30:21 +01:00
Lothar Rubusch 8bf57429fc cansniffer: simplify conditional cases
refactoring, reduce some levels of indention

Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
2021-10-18 22:30:21 +01:00
Lothar Rubusch 93a6cd6dfb cansniffer: simplify, avoiding else case indention
refactoring

Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
2021-10-18 22:08:44 +01:00
Lothar Rubusch d9368a6003 cansniffer: simplify logic
refactoring

Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
2021-10-18 22:08:05 +01:00
Lothar Rubusch c36bdc743f cansniffer: fix warning on unused variable
make use of former (not really) used "ret" in main()

Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
2021-10-18 22:02:21 +01:00
Oliver Hartkopp f7307b8290 can-utils: check for return values of if_nametoindex()
if_nametoindex() returns zero and a specific errno in the case the network
interface does not exist. The missing check leads to the use of the 'any'
CAN device but leaves the user alone as the user gets no error message.

Reported-by: Lothar Rubusch <lotophagon@protonmail.com>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2021-10-18 09:37:46 +02:00
Marc Kleine-BuddeandGitHub 5a3d1703d2 Merge pull request #314 from gibsson/master
j1939cat: fix comparison signs issue
2021-10-13 16:48:40 +02:00
Gary Bisson 57cc73d413 j1939cat: fix comparison signs issue
Signed-off-by: Gary Bisson <gary.bisson@boundarydevices.com>
2021-10-13 16:32:32 +02:00
Marc Kleine-BuddeandGitHub 4236614ab6 Merge pull request #315 from marckleinebudde/can-calc-bit-timing
can-calc-bit-timing: can_fixup_bittiming(): change type of tseg1 and alltseg to unsigned int
2021-10-13 15:25:26 +02:00
Marc Kleine-Budde e03f3e1049 can-calc-bit-timing: can_fixup_bittiming(): change type of tseg1 and alltseg to unsigned int
All timing calculation is done with unsigned integers, so change type
of tseg1 and alltseg to unsigned int, too.

Link: https://lore.kernel.org/all/20211013130653.1513627-1-mkl@pengutronix.de
Link: https://github.com/linux-can/can-utils/pull/314
Reported-by: Gary Bisson <bisson.gary@gmail.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2021-10-13 15:21:56 +02:00
Oliver Hartkopp 7b8457ce9f j1939cat: fix long long unsigned int warning in x_name printf
warning: format ‘%llx’ expects argument of type ‘long long unsigned int’, but argument 8 has type ‘uint64_t’ {aka ‘long unsigned int’} [-Wformat=]

Fixes: cc155d2f63 ("j1939cat: make use of new RX UAPI")
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
2021-10-11 20:54:22 +02:00
Marc Kleine-BuddeandGitHub 9f269db070 Merge pull request #311 from olerem/j1939-rx-2021.07.16
J1939 rx state support
2021-08-20 13:56:50 +02:00
Oleksij Rempel cc155d2f63 j1939cat: make use of new RX UAPI
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2021-08-20 13:38:42 +02:00
Oleksij Rempel 0107f07d83 include: import j1939.h from kernel v5.14-rc5+netdev-next
Import latest j1939.h to provide support for the RX state notifications

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
2021-08-20 10:21:20 +02:00
62 changed files with 7704 additions and 1961 deletions
+70
View File
@@ -0,0 +1,70 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '29 21 * * 1'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'cpp' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
+1
View File
@@ -20,6 +20,7 @@ GNUmakefile.in
/config/m4/ltsugar.m4
/config/m4/ltversion.m4
/config/m4/lt~obsolete.m4
/calc-bit-timing/.dirstamp
/mcp251xfd/.dirstamp
/asc2log
+1 -1
View File
@@ -181,7 +181,7 @@ include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := can-calc-bit-timing.c
LOCAL_SRC_FILES := calc-bit-timing/can-calc-bit-timing.c
LOCAL_MODULE := can-calc-bit-timing
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/
+9 -6
View File
@@ -9,10 +9,7 @@ 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()
add_definitions(-D_GNU_SOURCE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-parentheses")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-strict-aliasing")
@@ -21,6 +18,9 @@ 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")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DCLOCK_TAI=11")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSO_TXTIME=61")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSCM_TXTIME=SO_TXTIME")
include_directories (.)
include_directories (./include)
@@ -36,6 +36,7 @@ set(PROGRAMS_CANLIB
cansequence
log2asc
log2long
slcanpty
)
set(PROGRAMS_J1939
@@ -49,7 +50,6 @@ set(PROGRAMS_J1939
set(PROGRAMS
${PROGRAMS_CANLIB}
bcmserver
can-calc-bit-timing
canfdtest
cangw
cansniffer
@@ -62,7 +62,10 @@ set(PROGRAMS
isotptun
slcan_attach
slcand
slcanpty
)
add_executable(can-calc-bit-timing
calc-bit-timing/can-calc-bit-timing.c
)
add_executable(mcp251xfd-dump
+27 -3
View File
@@ -5,6 +5,8 @@ AM_CPPFLAGS = \
-I$(top_builddir)/include \
$(linux_CFLAGS)
EXTRA_DIST =
# link every app against libcan, it's static so it wouldn't hurt
LDADD = \
libcan.la
@@ -39,6 +41,16 @@ libcan_la_SOURCES = \
libj1939_la_SOURCES = \
libj1939.c
can_calc_bit_timing_SOURCES = \
calc-bit-timing/can-calc-bit-timing.c
EXTRA_DIST += \
calc-bit-timing/can-calc-bit-timing-v2_6_31.c \
calc-bit-timing/can-calc-bit-timing-v3_18.c \
calc-bit-timing/can-calc-bit-timing-v4_8.c \
calc-bit-timing/can-calc-bit-timing-v5_16.c \
calc-bit-timing/can-calc-bit-timing-v5_19.c
mcp251xfd_dump_SOURCES = \
mcp251xfd/mcp251xfd-dev-coredump.c \
mcp251xfd/mcp251xfd-dump-userspace.h \
@@ -48,6 +60,19 @@ mcp251xfd_dump_SOURCES = \
mcp251xfd/mcp251xfd-regmap.c \
mcp251xfd/mcp251xfd.h
EXTRA_DIST += \
mcp251xfd/99-devcoredump.rules \
mcp251xfd/data/devcoredump-canfd-v5.15.dump \
mcp251xfd/data/devcoredump-canfd.dump \
mcp251xfd/data/devcoredump-classic-can-v5.15.dump \
mcp251xfd/data/devcoredump-classic-can.dump \
mcp251xfd/data/registers-canfd-v5.15.dump \
mcp251xfd/data/registers-canfd.dump \
mcp251xfd/data/registers-classic-can-v5.15.dump \
mcp251xfd/data/registers-classic-can.dump \
mcp251xfd/devcoredump \
mcp251xfd/mcp251xfd-gen-testdata.sh
bin_PROGRAMS = \
asc2log \
bcmserver \
@@ -87,15 +112,14 @@ j1939spy_LDADD = libj1939.la
j1939sr_LDADD = libj1939.la
testj1939_LDADD = libj1939.la
EXTRA_DIST = \
EXTRA_DIST += \
.travis.yml \
Android.mk \
README.md \
autogen.sh \
can-j1939-kickstart.md \
can-j1939.md \
mcp251xfd/99-devcoredump.rules \
mcp251xfd/devcoredump
can-tc-init-etf.sh
MAINTAINERCLEANFILES = \
configure \
+13 -6
View File
@@ -46,11 +46,15 @@ MAKEFLAGS := -k
CFLAGS := -O2 -Wall -Wno-parentheses
CPPFLAGS += \
-I. \
-Iinclude \
-DAF_CAN=PF_CAN \
-DPF_CAN=29 \
-DSO_RXQ_OVFL=40 \
-DSCM_TIMESTAMPING_OPT_STATS=54 \
-DCLOCK_TAI=11 \
-DSO_TXTIME=61 \
-DSCM_TXTIME=SO_TXTIME \
-D_FILE_OFFSET_BITS=64 \
-D_GNU_SOURCE
@@ -102,25 +106,24 @@ PROGRAMS := \
all: $(PROGRAMS)
clean:
rm -f $(PROGRAMS) *.o
rm -f $(PROGRAMS) *.o mcp251xfd/*.o
install:
mkdir -p $(DESTDIR)$(PREFIX)/bin
cp -f $(PROGRAMS) $(DESTDIR)$(PREFIX)/bin
distclean:
rm -f $(PROGRAMS) $(LIBRARIES) *.o *~
distclean: clean
rm -f $(PROGRAMS) $(LIBRARIES) *~
asc2log.o: lib.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
slcanpty.o: lib.h
j1939acd.o: libj1939.h
j1939cat.o: libj1939.h
j1939spy.o: libj1939.h
@@ -137,6 +140,7 @@ cansend: cansend.o lib.o
cansequence: cansequence.o lib.o
log2asc: log2asc.o lib.o
log2long: log2long.o lib.o
slcanpty: slcanpty.o lib.o
j1939acd: j1939acd.o libj1939.o
j1939cat: j1939cat.o libj1939.o
j1939spy: j1939spy.o libj1939.o
@@ -144,5 +148,8 @@ j1939sr: j1939sr.o libj1939.o
testj1939: testj1939.o libj1939.o
canbusload: canbusload.o canframelen.o
mcp251xfd-dump: mcp251xfd/mcp251xfd-dev-coredump.o mcp251xfd/mcp251xfd-dump.o mcp251xfd/mcp251xfd-main.o mcp251xfd/mcp251xfd-regmap.o
can-calc-bit-timing: calc-bit-timing/can-calc-bit-timing.o
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
mcp251xfd-dump: mcp251xfd/mcp251xfd-dev-coredump.o mcp251xfd/mcp251xfd-dump.o mcp251xfd/mcp251xfd-main.o mcp251xfd/mcp251xfd-regmap.o
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
+83 -62
View File
@@ -50,6 +50,7 @@
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <limits.h>
#include <linux/can.h>
#include <linux/can/error.h>
@@ -131,74 +132,15 @@ void eval_can(char* buf, struct timeval *date_tvp, char timestamps, char base, i
static struct timeval tv; /* current frame timestamp */
static struct timeval read_tv; /* frame timestamp from ASC file */
struct canfd_frame cf;
struct can_frame *ccf = (struct can_frame *)&cf; /* for len8_dlc */
char rtr;
int dlc = 0;
int len = 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;
}
int i, items;
/* check for ErrorFrames */
if (sscanf(buf, "%lu.%lu %d %s",
@@ -215,8 +157,79 @@ void eval_can(char* buf, struct timeval *date_tvp, char timestamps, char base, i
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
prframe(outfile, &tv, interface, &cf, CAN_MAX_DLEN, "\n");
fflush(outfile);
return;
}
}
/* 0.002367 1 390x Rx d 8 17 00 14 00 C0 00 08 00 */
/* check for CAN frames with (hexa)decimal values */
if (base == 'h')
items = sscanf(buf, "%lu.%lu %d %s %2s %c %x %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]);
else
items = sscanf(buf, "%lu.%lu %d %s %2s %c %x %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 < 7 ) /* make sure we've read the dlc */
return;
/* dlc is one character hex value 0..F */
if (dlc > CAN_MAX_RAW_DLC)
return;
/* retrieve real data length */
if (dlc > CAN_MAX_DLC)
len = CAN_MAX_DLEN;
else
len = dlc;
if ((items == len + 7 ) || /* data frame */
((items == 6) && (rtr == 'r')) || /* RTR without DLC */
((items == 7) && (rtr == 'r'))) { /* RTR with DLC */
/* check for CAN ID with (hexa)decimal value */
if (base == 'h')
get_can_id(&cf, tmp1, 16);
else
get_can_id(&cf, tmp1, 10);
/* dlc > 8 => len == CAN_MAX_DLEN => fill len8_dlc value */
if (dlc > CAN_MAX_DLC)
ccf->len8_dlc = dlc;
if (strlen(dir) != 2) /* "Rx" or "Tx" */
return;
/* check for signed integer overflow */
if (dplace == 4 && read_tv.tv_usec >= INT_MAX / 100)
return;
if (dplace == 5 && read_tv.tv_usec >= INT_MAX / 10)
return;
if (dir[0] == 'R')
extra_info = " R\n";
else
extra_info = " T\n";
cf.len = len;
if (rtr == 'r')
cf.can_id |= CAN_RTR_FLAG;
else
for (i = 0; i < len; 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);
}
}
void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps, int dplace, FILE *outfile) {
@@ -264,6 +277,14 @@ void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps, int dplace
if (strlen(dir) != 2) /* "Rx" or "Tx" */
return;
/* check for signed integer overflow */
if (dplace == 4 && read_tv.tv_usec >= INT_MAX / 100)
return;
/* check for signed integer overflow */
if (dplace == 5 && read_tv.tv_usec >= INT_MAX / 10)
return;
if (dir[0] == 'R')
extra_info = " R\n";
else
@@ -0,0 +1,190 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* imported from v2.6.31-rc1~330^2~376
*
* 39549eef3587 can: CAN Network device driver and Netlink interface
*
* cherry-picked for easier integration:
* 61463a30f652 can: make function can_get_bittiming static
* aabdfd6adb80 can: replace the dev_dbg/info/err/... with the new netdev_xxx macros
* 08da7da41ea4 can: provide a separate bittiming_const parameter to bittiming functions
* b25a437206ed can: dev: remove unused variable from can_calc_bittiming() function
*/
/*
* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
* Copyright (C) 2006 Andrey Volkov, Varma Electronics
* Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
*
* 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
*
* 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
*/
/*
* Bit-timing calculation derived from:
*
* Code based on LinCAN sources and H8S2638 project
* Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
* Copyright 2005 Stanislav Marek
* email: pisa@cmp.felk.cvut.cz
*
* Calculates proper bit-timing parameters for a specified bit-rate
* and sample-point, which can then be used to set the bit-timing
* registers of the CAN controller. You can find more information
* in the header file linux/can/netlink.h.
*/
static int can_update_spt(const struct can_bittiming_const *btc,
int sampl_pt, int tseg, int *tseg1, int *tseg2)
{
*tseg2 = tseg + 1 - (sampl_pt * (tseg + 1)) / 1000;
if (*tseg2 < btc->tseg2_min)
*tseg2 = btc->tseg2_min;
if (*tseg2 > btc->tseg2_max)
*tseg2 = btc->tseg2_max;
*tseg1 = tseg - *tseg2;
if (*tseg1 > btc->tseg1_max) {
*tseg1 = btc->tseg1_max;
*tseg2 = tseg - *tseg1;
}
return 1000 * (tseg + 1 - *tseg2) / (tseg + 1);
}
static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc)
{
struct can_priv *priv = netdev_priv(dev);
long best_error = 1000000000, error = 0;
int best_tseg = 0, best_brp = 0, brp = 0;
int tsegall, tseg = 0, tseg1 = 0, tseg2 = 0;
int spt_error = 1000, spt = 0, sampl_pt;
long rate;
u64 v64;
/* Use CIA recommended sample points */
if (bt->sample_point) {
sampl_pt = bt->sample_point;
} else {
if (bt->bitrate > 800000)
sampl_pt = 750;
else if (bt->bitrate > 500000)
sampl_pt = 800;
else
sampl_pt = 875;
}
/* tseg even = round down, odd = round up */
for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1;
tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) {
tsegall = 1 + tseg / 2;
/* Compute all possible tseg choices (tseg=tseg1+tseg2) */
brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2;
/* chose brp step which is possible in system */
brp = (brp / btc->brp_inc) * btc->brp_inc;
if ((brp < btc->brp_min) || (brp > btc->brp_max))
continue;
rate = priv->clock.freq / (brp * tsegall);
error = bt->bitrate - rate;
/* tseg brp biterror */
if (error < 0)
error = -error;
if (error > best_error)
continue;
best_error = error;
if (error == 0) {
spt = can_update_spt(btc, sampl_pt, tseg / 2,
&tseg1, &tseg2);
error = sampl_pt - spt;
if (error < 0)
error = -error;
if (error > spt_error)
continue;
spt_error = error;
}
best_tseg = tseg / 2;
best_brp = brp;
if (error == 0)
break;
}
if (best_error) {
/* Error in one-tenth of a percent */
error = (best_error * 1000) / bt->bitrate;
if (error > CAN_CALC_MAX_ERROR) {
netdev_err(dev,
"bitrate error %ld.%ld%% too high\n",
error / 10, error % 10);
return -EDOM;
} else {
netdev_warn(dev, "bitrate error %ld.%ld%%\n",
error / 10, error % 10);
}
}
/* real sample point */
bt->sample_point = can_update_spt(btc, sampl_pt, best_tseg,
&tseg1, &tseg2);
v64 = (u64)best_brp * 1000000000UL;
do_div(v64, priv->clock.freq);
bt->tq = (u32)v64;
bt->prop_seg = tseg1 / 2;
bt->phase_seg1 = tseg1 - bt->prop_seg;
bt->phase_seg2 = tseg2;
bt->sjw = 1;
bt->brp = best_brp;
/* real bit-rate */
bt->bitrate = priv->clock.freq / (bt->brp * (tseg1 + tseg2 + 1));
return 0;
}
/*
* Checks the validity of the specified bit-timing parameters prop_seg,
* phase_seg1, phase_seg2 and sjw and tries to determine the bitrate
* prescaler value brp. You can find more information in the header
* file linux/can/netlink.h.
*/
static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc)
{
struct can_priv *priv = netdev_priv(dev);
int tseg1, alltseg;
u64 brp64;
tseg1 = bt->prop_seg + bt->phase_seg1;
if (!bt->sjw)
bt->sjw = 1;
if (bt->sjw > btc->sjw_max ||
tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max ||
bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max)
return -ERANGE;
brp64 = (u64)priv->clock.freq * (u64)bt->tq;
if (btc->brp_inc > 1)
do_div(brp64, btc->brp_inc);
brp64 += 500000000UL - 1;
do_div(brp64, 1000000000UL); /* the practicable BRP */
if (btc->brp_inc > 1)
brp64 *= btc->brp_inc;
bt->brp = (u32)brp64;
if (bt->brp < btc->brp_min || bt->brp > btc->brp_max)
return -EINVAL;
alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1;
bt->bitrate = priv->clock.freq / (bt->brp * alltseg);
bt->sample_point = ((tseg1 + 1) * 1000) / alltseg;
return 0;
}
+194
View File
@@ -0,0 +1,194 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* imported from v3.18-rc1~52^2~248^2~1
*
*/
/*
* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
* Copyright (C) 2006 Andrey Volkov, Varma Electronics
* Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
*
* 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
*
* 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, see <http://www.gnu.org/licenses/>.
*/
/*
* Bit-timing calculation derived from:
*
* Code based on LinCAN sources and H8S2638 project
* Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
* Copyright 2005 Stanislav Marek
* email: pisa@cmp.felk.cvut.cz
*
* Calculates proper bit-timing parameters for a specified bit-rate
* and sample-point, which can then be used to set the bit-timing
* registers of the CAN controller. You can find more information
* in the header file linux/can/netlink.h.
*/
static int can_update_spt(const struct can_bittiming_const *btc,
int sampl_pt, int tseg, int *tseg1, int *tseg2)
{
*tseg2 = tseg + 1 - (sampl_pt * (tseg + 1)) / 1000;
if (*tseg2 < btc->tseg2_min)
*tseg2 = btc->tseg2_min;
if (*tseg2 > btc->tseg2_max)
*tseg2 = btc->tseg2_max;
*tseg1 = tseg - *tseg2;
if (*tseg1 > btc->tseg1_max) {
*tseg1 = btc->tseg1_max;
*tseg2 = tseg - *tseg1;
}
return 1000 * (tseg + 1 - *tseg2) / (tseg + 1);
}
static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc)
{
struct can_priv *priv = netdev_priv(dev);
long best_error = 1000000000, error = 0;
int best_tseg = 0, best_brp = 0, brp = 0;
int tsegall, tseg = 0, tseg1 = 0, tseg2 = 0;
int spt_error = 1000, spt = 0, sampl_pt;
long rate;
u64 v64;
/* Use CIA recommended sample points */
if (bt->sample_point) {
sampl_pt = bt->sample_point;
} else {
if (bt->bitrate > 800000)
sampl_pt = 750;
else if (bt->bitrate > 500000)
sampl_pt = 800;
else
sampl_pt = 875;
}
/* tseg even = round down, odd = round up */
for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1;
tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) {
tsegall = 1 + tseg / 2;
/* Compute all possible tseg choices (tseg=tseg1+tseg2) */
brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2;
/* chose brp step which is possible in system */
brp = (brp / btc->brp_inc) * btc->brp_inc;
if ((brp < btc->brp_min) || (brp > btc->brp_max))
continue;
rate = priv->clock.freq / (brp * tsegall);
error = bt->bitrate - rate;
/* tseg brp biterror */
if (error < 0)
error = -error;
if (error > best_error)
continue;
best_error = error;
if (error == 0) {
spt = can_update_spt(btc, sampl_pt, tseg / 2,
&tseg1, &tseg2);
error = sampl_pt - spt;
if (error < 0)
error = -error;
if (error > spt_error)
continue;
spt_error = error;
}
best_tseg = tseg / 2;
best_brp = brp;
if (error == 0)
break;
}
if (best_error) {
/* Error in one-tenth of a percent */
error = (best_error * 1000) / bt->bitrate;
if (error > CAN_CALC_MAX_ERROR) {
netdev_err(dev,
"bitrate error %ld.%ld%% too high\n",
error / 10, error % 10);
return -EDOM;
} else {
netdev_warn(dev, "bitrate error %ld.%ld%%\n",
error / 10, error % 10);
}
}
/* real sample point */
bt->sample_point = can_update_spt(btc, sampl_pt, best_tseg,
&tseg1, &tseg2);
v64 = (u64)best_brp * 1000000000UL;
do_div(v64, priv->clock.freq);
bt->tq = (u32)v64;
bt->prop_seg = tseg1 / 2;
bt->phase_seg1 = tseg1 - bt->prop_seg;
bt->phase_seg2 = tseg2;
/* check for sjw user settings */
if (!bt->sjw || !btc->sjw_max)
bt->sjw = 1;
else {
/* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */
if (bt->sjw > btc->sjw_max)
bt->sjw = btc->sjw_max;
/* bt->sjw must not be higher than tseg2 */
if (tseg2 < bt->sjw)
bt->sjw = tseg2;
}
bt->brp = best_brp;
/* real bit-rate */
bt->bitrate = priv->clock.freq / (bt->brp * (tseg1 + tseg2 + 1));
return 0;
}
/*
* Checks the validity of the specified bit-timing parameters prop_seg,
* phase_seg1, phase_seg2 and sjw and tries to determine the bitrate
* prescaler value brp. You can find more information in the header
* file linux/can/netlink.h.
*/
static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc)
{
struct can_priv *priv = netdev_priv(dev);
int tseg1, alltseg;
u64 brp64;
tseg1 = bt->prop_seg + bt->phase_seg1;
if (!bt->sjw)
bt->sjw = 1;
if (bt->sjw > btc->sjw_max ||
tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max ||
bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max)
return -ERANGE;
brp64 = (u64)priv->clock.freq * (u64)bt->tq;
if (btc->brp_inc > 1)
do_div(brp64, btc->brp_inc);
brp64 += 500000000UL - 1;
do_div(brp64, 1000000000UL); /* the practicable BRP */
if (btc->brp_inc > 1)
brp64 *= btc->brp_inc;
bt->brp = (u32)brp64;
if (bt->brp < btc->brp_min || bt->brp > btc->brp_max)
return -EINVAL;
alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1;
bt->bitrate = priv->clock.freq / (bt->brp * alltseg);
bt->sample_point = ((tseg1 + 1) * 1000) / alltseg;
return 0;
}
+223
View File
@@ -0,0 +1,223 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* imported from v4.8-rc1~140^2~304^2~11
*
*/
/*
* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
* Copyright (C) 2006 Andrey Volkov, Varma Electronics
* Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
*
* 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
*
* 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, see <http://www.gnu.org/licenses/>.
*/
/*
* Bit-timing calculation derived from:
*
* Code based on LinCAN sources and H8S2638 project
* Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
* Copyright 2005 Stanislav Marek
* email: pisa@cmp.felk.cvut.cz
*
* Calculates proper bit-timing parameters for a specified bit-rate
* and sample-point, which can then be used to set the bit-timing
* registers of the CAN controller. You can find more information
* in the header file linux/can/netlink.h.
*/
static int can_update_sample_point(const struct can_bittiming_const *btc,
unsigned int sample_point_nominal, unsigned int tseg,
unsigned int *tseg1_ptr, unsigned int *tseg2_ptr,
unsigned int *sample_point_error_ptr)
{
unsigned int sample_point_error, best_sample_point_error = UINT_MAX;
unsigned int sample_point, best_sample_point = 0;
unsigned int tseg1, tseg2;
int i;
for (i = 0; i <= 1; i++) {
tseg2 = tseg + CAN_CALC_SYNC_SEG - (sample_point_nominal * (tseg + CAN_CALC_SYNC_SEG)) / 1000 - i;
tseg2 = clamp(tseg2, btc->tseg2_min, btc->tseg2_max);
tseg1 = tseg - tseg2;
if (tseg1 > btc->tseg1_max) {
tseg1 = btc->tseg1_max;
tseg2 = tseg - tseg1;
}
sample_point = 1000 * (tseg + CAN_CALC_SYNC_SEG - tseg2) / (tseg + CAN_CALC_SYNC_SEG);
sample_point_error = abs(sample_point_nominal - sample_point);
if ((sample_point <= sample_point_nominal) && (sample_point_error < best_sample_point_error)) {
best_sample_point = sample_point;
best_sample_point_error = sample_point_error;
*tseg1_ptr = tseg1;
*tseg2_ptr = tseg2;
}
}
if (sample_point_error_ptr)
*sample_point_error_ptr = best_sample_point_error;
return best_sample_point;
}
static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc)
{
struct can_priv *priv = netdev_priv(dev);
unsigned int bitrate; /* current bitrate */
unsigned int bitrate_error; /* difference between current and nominal value */
unsigned int best_bitrate_error = UINT_MAX;
unsigned int sample_point_error; /* difference between current and nominal value */
unsigned int best_sample_point_error = UINT_MAX;
unsigned int sample_point_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 = 0, tseg2 = 0;
u64 v64;
/* Use CiA recommended sample points */
if (bt->sample_point) {
sample_point_nominal = bt->sample_point;
} else {
if (bt->bitrate > 800000)
sample_point_nominal = 750;
else if (bt->bitrate > 500000)
sample_point_nominal = 800;
else
sample_point_nominal = 875;
}
/* tseg even = round down, odd = round up */
for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1;
tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) {
tsegall = CAN_CALC_SYNC_SEG + tseg / 2;
/* Compute all possible tseg choices (tseg=tseg1+tseg2) */
brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2;
/* choose brp step which is possible in system */
brp = (brp / btc->brp_inc) * btc->brp_inc;
if ((brp < btc->brp_min) || (brp > btc->brp_max))
continue;
bitrate = priv->clock.freq / (brp * tsegall);
bitrate_error = abs(bt->bitrate - bitrate);
/* tseg brp biterror */
if (bitrate_error > best_bitrate_error)
continue;
/* reset sample point error if we have a better bitrate */
if (bitrate_error < best_bitrate_error)
best_sample_point_error = UINT_MAX;
can_update_sample_point(btc, sample_point_nominal, tseg / 2, &tseg1, &tseg2, &sample_point_error);
if (sample_point_error > best_sample_point_error)
continue;
best_sample_point_error = sample_point_error;
best_bitrate_error = bitrate_error;
best_tseg = tseg / 2;
best_brp = brp;
if (bitrate_error == 0 && sample_point_error == 0)
break;
}
if (best_bitrate_error) {
/* Error in one-tenth of a percent */
v64 = (u64)best_bitrate_error * 1000;
do_div(v64, bt->bitrate);
bitrate_error = (u32)v64;
if (bitrate_error > CAN_CALC_MAX_ERROR) {
netdev_err(dev,
"bitrate error %d.%d%% too high\n",
bitrate_error / 10, bitrate_error % 10);
return -EDOM;
}
netdev_warn(dev, "bitrate error %d.%d%%\n",
bitrate_error / 10, bitrate_error % 10);
}
/* real sample point */
bt->sample_point = can_update_sample_point(btc, sample_point_nominal, best_tseg,
&tseg1, &tseg2, NULL);
v64 = (u64)best_brp * 1000 * 1000 * 1000;
do_div(v64, priv->clock.freq);
bt->tq = (u32)v64;
bt->prop_seg = tseg1 / 2;
bt->phase_seg1 = tseg1 - bt->prop_seg;
bt->phase_seg2 = tseg2;
/* check for sjw user settings */
if (!bt->sjw || !btc->sjw_max) {
bt->sjw = 1;
} else {
/* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */
if (bt->sjw > btc->sjw_max)
bt->sjw = btc->sjw_max;
/* bt->sjw must not be higher than tseg2 */
if (tseg2 < bt->sjw)
bt->sjw = tseg2;
}
bt->brp = best_brp;
/* real bitrate */
bt->bitrate = priv->clock.freq / (bt->brp * (CAN_CALC_SYNC_SEG + tseg1 + tseg2));
return 0;
}
/*
* Checks the validity of the specified bit-timing parameters prop_seg,
* phase_seg1, phase_seg2 and sjw and tries to determine the bitrate
* prescaler value brp. You can find more information in the header
* file linux/can/netlink.h.
*/
static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc)
{
struct can_priv *priv = netdev_priv(dev);
int tseg1, alltseg;
u64 brp64;
tseg1 = bt->prop_seg + bt->phase_seg1;
if (!bt->sjw)
bt->sjw = 1;
if (bt->sjw > btc->sjw_max ||
tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max ||
bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max)
return -ERANGE;
brp64 = (u64)priv->clock.freq * (u64)bt->tq;
if (btc->brp_inc > 1)
do_div(brp64, btc->brp_inc);
brp64 += 500000000UL - 1;
do_div(brp64, 1000000000UL); /* the practicable BRP */
if (btc->brp_inc > 1)
brp64 *= btc->brp_inc;
bt->brp = (u32)brp64;
if (bt->brp < btc->brp_min || bt->brp > btc->brp_max)
return -EINVAL;
alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1;
bt->bitrate = priv->clock.freq / (bt->brp * alltseg);
bt->sample_point = ((tseg1 + 1) * 1000) / alltseg;
return 0;
}
+216
View File
@@ -0,0 +1,216 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* imported from v5.16-rc1~159^2~104^2~13
*
*/
/* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
* Copyright (C) 2006 Andrey Volkov, Varma Electronics
* Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
*/
/* Bit-timing calculation derived from:
*
* Code based on LinCAN sources and H8S2638 project
* Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
* Copyright 2005 Stanislav Marek
* email: pisa@cmp.felk.cvut.cz
*
* Calculates proper bit-timing parameters for a specified bit-rate
* and sample-point, which can then be used to set the bit-timing
* registers of the CAN controller. You can find more information
* in the header file linux/can/netlink.h.
*/
static int
can_update_sample_point(const struct can_bittiming_const *btc,
unsigned int sample_point_nominal, unsigned int tseg,
unsigned int *tseg1_ptr, unsigned int *tseg2_ptr,
unsigned int *sample_point_error_ptr)
{
unsigned int sample_point_error, best_sample_point_error = UINT_MAX;
unsigned int sample_point, best_sample_point = 0;
unsigned int tseg1, tseg2;
int i;
for (i = 0; i <= 1; i++) {
tseg2 = tseg + CAN_SYNC_SEG -
(sample_point_nominal * (tseg + CAN_SYNC_SEG)) /
1000 - i;
tseg2 = clamp(tseg2, btc->tseg2_min, btc->tseg2_max);
tseg1 = tseg - tseg2;
if (tseg1 > btc->tseg1_max) {
tseg1 = btc->tseg1_max;
tseg2 = tseg - tseg1;
}
sample_point = 1000 * (tseg + CAN_SYNC_SEG - tseg2) /
(tseg + CAN_SYNC_SEG);
sample_point_error = abs(sample_point_nominal - sample_point);
if (sample_point <= sample_point_nominal &&
sample_point_error < best_sample_point_error) {
best_sample_point = sample_point;
best_sample_point_error = sample_point_error;
*tseg1_ptr = tseg1;
*tseg2_ptr = tseg2;
}
}
if (sample_point_error_ptr)
*sample_point_error_ptr = best_sample_point_error;
return best_sample_point;
}
int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc)
{
struct can_priv *priv = netdev_priv(dev);
unsigned int bitrate; /* current bitrate */
unsigned int bitrate_error; /* difference between current and nominal value */
unsigned int best_bitrate_error = UINT_MAX;
unsigned int sample_point_error; /* difference between current and nominal value */
unsigned int best_sample_point_error = UINT_MAX;
unsigned int sample_point_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 = 0, tseg2 = 0;
u64 v64;
/* Use CiA recommended sample points */
if (bt->sample_point) {
sample_point_nominal = bt->sample_point;
} else {
if (bt->bitrate > 800 * CAN_KBPS)
sample_point_nominal = 750;
else if (bt->bitrate > 500 * CAN_KBPS)
sample_point_nominal = 800;
else
sample_point_nominal = 875;
}
/* tseg even = round down, odd = round up */
for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1;
tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) {
tsegall = CAN_SYNC_SEG + tseg / 2;
/* Compute all possible tseg choices (tseg=tseg1+tseg2) */
brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2;
/* choose brp step which is possible in system */
brp = (brp / btc->brp_inc) * btc->brp_inc;
if (brp < btc->brp_min || brp > btc->brp_max)
continue;
bitrate = priv->clock.freq / (brp * tsegall);
bitrate_error = abs(bt->bitrate - bitrate);
/* tseg brp biterror */
if (bitrate_error > best_bitrate_error)
continue;
/* reset sample point error if we have a better bitrate */
if (bitrate_error < best_bitrate_error)
best_sample_point_error = UINT_MAX;
can_update_sample_point(btc, sample_point_nominal, tseg / 2,
&tseg1, &tseg2, &sample_point_error);
if (sample_point_error > best_sample_point_error)
continue;
best_sample_point_error = sample_point_error;
best_bitrate_error = bitrate_error;
best_tseg = tseg / 2;
best_brp = brp;
if (bitrate_error == 0 && sample_point_error == 0)
break;
}
if (best_bitrate_error) {
/* Error in one-tenth of a percent */
v64 = (u64)best_bitrate_error * 1000;
do_div(v64, bt->bitrate);
bitrate_error = (u32)v64;
if (bitrate_error > CAN_CALC_MAX_ERROR) {
netdev_err(dev,
"bitrate error %d.%d%% too high\n",
bitrate_error / 10, bitrate_error % 10);
return -EDOM;
}
netdev_warn(dev, "bitrate error %d.%d%%\n",
bitrate_error / 10, bitrate_error % 10);
}
/* real sample point */
bt->sample_point = can_update_sample_point(btc, sample_point_nominal,
best_tseg, &tseg1, &tseg2,
NULL);
v64 = (u64)best_brp * 1000 * 1000 * 1000;
do_div(v64, priv->clock.freq);
bt->tq = (u32)v64;
bt->prop_seg = tseg1 / 2;
bt->phase_seg1 = tseg1 - bt->prop_seg;
bt->phase_seg2 = tseg2;
/* check for sjw user settings */
if (!bt->sjw || !btc->sjw_max) {
bt->sjw = 1;
} else {
/* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */
if (bt->sjw > btc->sjw_max)
bt->sjw = btc->sjw_max;
/* bt->sjw must not be higher than tseg2 */
if (tseg2 < bt->sjw)
bt->sjw = tseg2;
}
bt->brp = best_brp;
/* real bitrate */
bt->bitrate = priv->clock.freq /
(bt->brp * (CAN_SYNC_SEG + tseg1 + tseg2));
return 0;
}
/* Checks the validity of the specified bit-timing parameters prop_seg,
* phase_seg1, phase_seg2 and sjw and tries to determine the bitrate
* prescaler value brp. You can find more information in the header
* file linux/can/netlink.h.
*/
static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc)
{
struct can_priv *priv = netdev_priv(dev);
unsigned int tseg1, alltseg;
u64 brp64;
tseg1 = bt->prop_seg + bt->phase_seg1;
if (!bt->sjw)
bt->sjw = 1;
if (bt->sjw > btc->sjw_max ||
tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max ||
bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max)
return -ERANGE;
brp64 = (u64)priv->clock.freq * (u64)bt->tq;
if (btc->brp_inc > 1)
do_div(brp64, btc->brp_inc);
brp64 += 500000000UL - 1;
do_div(brp64, 1000000000UL); /* the practicable BRP */
if (btc->brp_inc > 1)
brp64 *= btc->brp_inc;
bt->brp = (u32)brp64;
if (bt->brp < btc->brp_min || bt->brp > btc->brp_max)
return -EINVAL;
alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1;
bt->bitrate = priv->clock.freq / (bt->brp * alltseg);
bt->sample_point = ((tseg1 + 1) * 1000) / alltseg;
return 0;
}
+216
View File
@@ -0,0 +1,216 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* imported from v5.19-rc1~159^2~286^2~15
*
*/
/* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
* Copyright (C) 2006 Andrey Volkov, Varma Electronics
* Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
*/
/* Bit-timing calculation derived from:
*
* Code based on LinCAN sources and H8S2638 project
* Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
* Copyright 2005 Stanislav Marek
* email: pisa@cmp.felk.cvut.cz
*
* Calculates proper bit-timing parameters for a specified bit-rate
* and sample-point, which can then be used to set the bit-timing
* registers of the CAN controller. You can find more information
* in the header file linux/can/netlink.h.
*/
static int
can_update_sample_point(const struct can_bittiming_const *btc,
const unsigned int sample_point_nominal, const unsigned int tseg,
unsigned int *tseg1_ptr, unsigned int *tseg2_ptr,
unsigned int *sample_point_error_ptr)
{
unsigned int sample_point_error, best_sample_point_error = UINT_MAX;
unsigned int sample_point, best_sample_point = 0;
unsigned int tseg1, tseg2;
int i;
for (i = 0; i <= 1; i++) {
tseg2 = tseg + CAN_SYNC_SEG -
(sample_point_nominal * (tseg + CAN_SYNC_SEG)) /
1000 - i;
tseg2 = clamp(tseg2, btc->tseg2_min, btc->tseg2_max);
tseg1 = tseg - tseg2;
if (tseg1 > btc->tseg1_max) {
tseg1 = btc->tseg1_max;
tseg2 = tseg - tseg1;
}
sample_point = 1000 * (tseg + CAN_SYNC_SEG - tseg2) /
(tseg + CAN_SYNC_SEG);
sample_point_error = abs(sample_point_nominal - sample_point);
if (sample_point <= sample_point_nominal &&
sample_point_error < best_sample_point_error) {
best_sample_point = sample_point;
best_sample_point_error = sample_point_error;
*tseg1_ptr = tseg1;
*tseg2_ptr = tseg2;
}
}
if (sample_point_error_ptr)
*sample_point_error_ptr = best_sample_point_error;
return best_sample_point;
}
int can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc)
{
struct can_priv *priv = netdev_priv(dev);
unsigned int bitrate; /* current bitrate */
unsigned int bitrate_error; /* difference between current and nominal value */
unsigned int best_bitrate_error = UINT_MAX;
unsigned int sample_point_error; /* difference between current and nominal value */
unsigned int best_sample_point_error = UINT_MAX;
unsigned int sample_point_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 = 0, tseg2 = 0;
u64 v64;
/* Use CiA recommended sample points */
if (bt->sample_point) {
sample_point_nominal = bt->sample_point;
} else {
if (bt->bitrate > 800 * KILO /* BPS */)
sample_point_nominal = 750;
else if (bt->bitrate > 500 * KILO /* BPS */)
sample_point_nominal = 800;
else
sample_point_nominal = 875;
}
/* tseg even = round down, odd = round up */
for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1;
tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) {
tsegall = CAN_SYNC_SEG + tseg / 2;
/* Compute all possible tseg choices (tseg=tseg1+tseg2) */
brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2;
/* choose brp step which is possible in system */
brp = (brp / btc->brp_inc) * btc->brp_inc;
if (brp < btc->brp_min || brp > btc->brp_max)
continue;
bitrate = priv->clock.freq / (brp * tsegall);
bitrate_error = abs(bt->bitrate - bitrate);
/* tseg brp biterror */
if (bitrate_error > best_bitrate_error)
continue;
/* reset sample point error if we have a better bitrate */
if (bitrate_error < best_bitrate_error)
best_sample_point_error = UINT_MAX;
can_update_sample_point(btc, sample_point_nominal, tseg / 2,
&tseg1, &tseg2, &sample_point_error);
if (sample_point_error >= best_sample_point_error)
continue;
best_sample_point_error = sample_point_error;
best_bitrate_error = bitrate_error;
best_tseg = tseg / 2;
best_brp = brp;
if (bitrate_error == 0 && sample_point_error == 0)
break;
}
if (best_bitrate_error) {
/* Error in one-tenth of a percent */
v64 = (u64)best_bitrate_error * 1000;
do_div(v64, bt->bitrate);
bitrate_error = (u32)v64;
if (bitrate_error > CAN_CALC_MAX_ERROR) {
netdev_err(dev,
"bitrate error %d.%d%% too high\n",
bitrate_error / 10, bitrate_error % 10);
return -EDOM;
}
netdev_warn(dev, "bitrate error %d.%d%%\n",
bitrate_error / 10, bitrate_error % 10);
}
/* real sample point */
bt->sample_point = can_update_sample_point(btc, sample_point_nominal,
best_tseg, &tseg1, &tseg2,
NULL);
v64 = (u64)best_brp * 1000 * 1000 * 1000;
do_div(v64, priv->clock.freq);
bt->tq = (u32)v64;
bt->prop_seg = tseg1 / 2;
bt->phase_seg1 = tseg1 - bt->prop_seg;
bt->phase_seg2 = tseg2;
/* check for sjw user settings */
if (!bt->sjw || !btc->sjw_max) {
bt->sjw = 1;
} else {
/* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */
if (bt->sjw > btc->sjw_max)
bt->sjw = btc->sjw_max;
/* bt->sjw must not be higher than tseg2 */
if (tseg2 < bt->sjw)
bt->sjw = tseg2;
}
bt->brp = best_brp;
/* real bitrate */
bt->bitrate = priv->clock.freq /
(bt->brp * (CAN_SYNC_SEG + tseg1 + tseg2));
return 0;
}
/* Checks the validity of the specified bit-timing parameters prop_seg,
* phase_seg1, phase_seg2 and sjw and tries to determine the bitrate
* prescaler value brp. You can find more information in the header
* file linux/can/netlink.h.
*/
static int can_fixup_bittiming(const struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc)
{
const struct can_priv *priv = netdev_priv(dev);
unsigned int tseg1, alltseg;
u64 brp64;
tseg1 = bt->prop_seg + bt->phase_seg1;
if (!bt->sjw)
bt->sjw = 1;
if (bt->sjw > btc->sjw_max ||
tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max ||
bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max)
return -ERANGE;
brp64 = (u64)priv->clock.freq * (u64)bt->tq;
if (btc->brp_inc > 1)
do_div(brp64, btc->brp_inc);
brp64 += 500000000UL - 1;
do_div(brp64, 1000000000UL); /* the practicable BRP */
if (btc->brp_inc > 1)
brp64 *= btc->brp_inc;
bt->brp = (u32)brp64;
if (bt->brp < btc->brp_min || bt->brp > btc->brp_max)
return -EINVAL;
alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1;
bt->bitrate = priv->clock.freq / (bt->brp * alltseg);
bt->sample_point = ((tseg1 + 1) * 1000) / alltseg;
return 0;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+59
View File
@@ -0,0 +1,59 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0-only
# Copyright (C) 2022 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
#
# This script requires a kernel compiled with the following options:
#
# CONFIG_NET_SCH_PRIO
# CONFIG_NET_SCH_ETF
# CONFIG_NET_CLS_BASIC
# CONFIG_NET_CLS_FW
# CONFIG_NET_EMATCH
# CONFIG_NET_EMATCH_CANID
#
set -e
IFACE=${1:-can0}
MARK=${2:-1}
clear() {
tc -batch - <<EOF
qdisc replace dev ${IFACE} root pfifo_fast
EOF
}
show() {
tc -batch - <<EOF
qdisc show dev ${IFACE}
filter show dev ${IFACE}
EOF
}
prio_etf_mark() {
tc -batch - <<EOF
qdisc replace dev ${IFACE} parent root handle 100 prio \
bands 3
qdisc replace dev ${IFACE} handle 1001 parent 100:1 etf clockid CLOCK_TAI \
delta 200000
qdisc replace dev ${IFACE} handle 1002 parent 100:3 pfifo_fast
filter add dev ${IFACE} parent 100: prio 1 \
handle ${MARK} fw flowid 100:1
filter add dev ${IFACE} parent 100: prio 2 \
basic match canid (sff 0x0:0x0 eff 0x0:0x0) flowid 100:2
EOF
}
clear
prio_etf_mark
show
+3 -6
View File
@@ -61,6 +61,7 @@
#include <linux/can.h>
#include <linux/can/raw.h>
#include "lib.h"
#include "terminal.h"
#include "canframelen.h"
@@ -310,9 +311,7 @@ int main(int argc, char **argv)
return 1;
}
#ifdef DEBUG
printf("open %d '%s'.\n", i, ptr);
#endif
pr_debug("open %d '%s'.\n", i, ptr);
s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (s[i] < 0) {
@@ -358,10 +357,8 @@ int main(int argc, char **argv)
if (nbytes > max_bitrate_len)
max_bitrate_len = nbytes; /* for nice printing */
pr_debug("using interface name '%s'.\n", ifr.ifr_name);
#ifdef DEBUG
printf("using interface name '%s'.\n", ifr.ifr_name);
#endif
/* try to switch the socket into CAN FD mode */
const int canfd_on = 1;
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &canfd_on, sizeof(canfd_on));
+78 -65
View File
@@ -63,6 +63,7 @@
#include <linux/can.h>
#include <linux/can/raw.h>
#include <linux/net_tstamp.h>
#include "terminal.h"
#include "lib.h"
@@ -72,10 +73,6 @@
#define SO_TIMESTAMPING 37
#endif
/* from #include <linux/net_tstamp.h> - since Linux 2.6.30 */
#define SOF_TIMESTAMPING_SOFTWARE (1 << 4)
#define SOF_TIMESTAMPING_RX_SOFTWARE (1 << 3)
#define SOF_TIMESTAMPING_RAW_HARDWARE (1 << 6)
#define TIMESTAMPSZ 50 /* string 'absolute with date' requires max 49 bytes */
#define MAXSOCK 16 /* max. number of CAN interfaces given on the cmdline */
@@ -108,6 +105,7 @@ struct if_info { /* bundled information per open socket */
};
static struct if_info sock_info[MAXSOCK];
static char *progname;
static char devname[MAXIFNAMES][IFNAMSIZ+1];
static int dindex[MAXIFNAMES];
static int max_devname_len; /* to prevent frazzled device name output */
@@ -121,11 +119,11 @@ extern int optind, opterr, optopt;
static volatile int running = 1;
static void print_usage(char *prg)
static void print_usage(void)
{
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, "%s - dump CAN bus traffic.\n", progname);
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", progname);
fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", progname);
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");
@@ -135,10 +133,11 @@ static void print_usage(char *prg)
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, " -l (log CAN-frames into file. Sets '-s %d' by default)\n", SILENT_ON);
fprintf(stderr, " -f <fname> (log CAN-frames into file <fname>. Sets '-s %d' by default)\n", SILENT_ON);
fprintf(stderr, " -L (use log file format on stdout)\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 (Don't exit if a \"detected\" can device goes down)\n");
fprintf(stderr, " -d (monitor dropped CAN frames)\n");
fprintf(stderr, " -e (dump CAN error frames in human-readable format)\n");
fprintf(stderr, " -8 (display raw DLC values in {} for Classical CAN)\n");
@@ -158,12 +157,12 @@ static void print_usage(char *prg)
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\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, "%s -c -c -ta can0,123:7FF,400:700,#000000FF can2,400~7F0 can3 can8\n\n", progname);
fprintf(stderr, "%s -l any,0~0,#FFFFFFFF\n (log only error frames but no(!) data frames)\n", progname);
fprintf(stderr, "%s -l any,0:0,#FFFFFFFF\n (log error frames and also all data frames)\n", progname);
fprintf(stderr, "%s vcan2,12345678:DFFFFFFF\n (match only for extended CAN ID 12345678)\n", progname);
fprintf(stderr, "%s vcan2,123:7FF\n (matches CAN ID 123 - including EFF and RTR frames)\n", progname);
fprintf(stderr, "%s vcan2,123:C00007FF\n (matches CAN ID 123 - only SFF and non-RTR frames)\n", progname);
fprintf(stderr, "\n");
}
@@ -215,9 +214,7 @@ static int idx2dindex(int ifidx, int socket)
strcpy(devname[i], ifr.ifr_name);
#ifdef DEBUG
printf("new index %d (%s)\n", i, devname[i]);
#endif
pr_debug("new index %d (%s)\n", i, devname[i]);
return i;
}
@@ -226,7 +223,6 @@ static inline void sprint_timestamp(const char timestamp, const struct timeval *
struct timeval *const last_tv, char *ts_buffer)
{
switch (timestamp) {
case 'a': /* absolute with timestamp */
sprintf(ts_buffer, "(%010lu.%06lu) ", tv->tv_sec, tv->tv_usec);
break;
@@ -302,7 +298,9 @@ int main(int argc, char **argv)
int join_filter;
char *ptr, *nptr;
struct sockaddr_can addr;
char ctrlmsg[CMSG_SPACE(sizeof(struct timeval) + 3 * sizeof(struct timespec) + sizeof(__u32))];
char ctrlmsg[CMSG_SPACE(sizeof(struct timeval)) +
CMSG_SPACE(3 * sizeof(struct timespec)) +
CMSG_SPACE(sizeof(__u32))];
struct iovec iov;
struct msghdr msg;
struct cmsghdr *cmsg;
@@ -314,6 +312,8 @@ int main(int argc, char **argv)
struct timeval tv, last_tv;
int timeout_ms = -1; /* default to no timeout */
FILE *logfile = NULL;
char fname[83]; /* suggested by -Wformat-overflow= */
const char *logname = NULL;
signal(SIGTERM, sigterm);
signal(SIGHUP, sigterm);
@@ -322,7 +322,9 @@ int main(int argc, char **argv)
last_tv.tv_sec = 0;
last_tv.tv_usec = 0;
while ((opt = getopt(argc, argv, "t:HciaSs:lDdxLn:r:he8T:?")) != -1) {
progname = basename(argv[0]);
while ((opt = getopt(argc, argv, "t:HciaSs:lf:Ln:r:Dde8xT:h?")) != -1) {
switch (opt) {
case 't':
timestamp = optarg[0];
@@ -330,7 +332,7 @@ int main(int argc, char **argv)
if ((timestamp != 'a') && (timestamp != 'A') &&
(timestamp != 'd') && (timestamp != 'z')) {
fprintf(stderr, "%s: unknown timestamp mode '%c' - ignored\n",
basename(argv[0]), optarg[0]);
progname, optarg[0]);
timestamp = 0;
}
if ((logtimestamp != 'a') && (logtimestamp != 'z')) {
@@ -369,7 +371,7 @@ int main(int argc, char **argv)
case 's':
silent = atoi(optarg);
if (silent > SILENT_ON) {
print_usage(basename(argv[0]));
print_usage();
exit(1);
}
break;
@@ -394,10 +396,15 @@ int main(int argc, char **argv)
logfrmt = 1;
break;
case 'f':
logname = optarg;
log = 1;
break;
case 'n':
count = atoi(optarg);
if (count < 1) {
print_usage(basename(argv[0]));
print_usage();
exit(1);
}
break;
@@ -405,7 +412,7 @@ int main(int argc, char **argv)
case 'r':
rcvbuf_size = atoi(optarg);
if (rcvbuf_size < 1) {
print_usage(basename(argv[0]));
print_usage();
exit(1);
}
break;
@@ -414,19 +421,19 @@ int main(int argc, char **argv)
errno = 0;
timeout_ms = strtol(optarg, NULL, 0);
if (errno != 0) {
print_usage(basename(argv[0]));
print_usage();
exit(1);
}
break;
default:
print_usage(basename(argv[0]));
print_usage();
exit(1);
break;
}
}
if (optind == argc) {
print_usage(basename(argv[0]));
print_usage();
exit(0);
}
@@ -435,6 +442,12 @@ int main(int argc, char **argv)
exit(0);
}
/* "-f -" is equal to "-L" (print logfile format on stdout) */
if (log && logname && strcmp("-", logname) == 0) {
log = 0; /* no logging into a file */
logfrmt = 1; /* print logformat output to stdout */
}
if (silent == SILENT_INI) {
if (log) {
fprintf(stderr, "Disabled standard output while logging.\n");
@@ -461,9 +474,7 @@ int main(int argc, char **argv)
ptr = argv[optind+i];
nptr = strchr(ptr, ',');
#ifdef DEBUG
printf("open %d '%s'.\n", i, ptr);
#endif
pr_debug("open %d '%s'.\n", i, ptr);
obj->s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (obj->s < 0) {
@@ -497,9 +508,7 @@ int main(int argc, char **argv)
memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
strncpy(ifr.ifr_name, ptr, nbytes);
#ifdef DEBUG
printf("using interface name '%s'.\n", ifr.ifr_name);
#endif
pr_debug("using interface name '%s'.\n", ifr.ifr_name);
if (strcmp(ANYDEV, ifr.ifr_name) != 0) {
if (ioctl(obj->s, SIOCGIFINDEX, &ifr) < 0) {
@@ -511,7 +520,6 @@ int main(int argc, char **argv)
addr.can_ifindex = 0; /* any can interface */
if (nptr) {
/* found a ',' after the interface name => check for filters */
/* determine number of filters to alloc the filter space */
@@ -589,9 +597,7 @@ int main(int argc, char **argv)
/* try SO_RCVBUFFORCE first, if we run with CAP_NET_ADMIN */
if (setsockopt(obj->s, SOL_SOCKET, SO_RCVBUFFORCE,
&rcvbuf_size, sizeof(rcvbuf_size)) < 0) {
#ifdef DEBUG
printf("SO_RCVBUFFORCE failed so try SO_RCVBUF ...\n");
#endif
pr_debug("SO_RCVBUFFORCE failed so try SO_RCVBUF ...\n");
if (setsockopt(obj->s, SOL_SOCKET, SO_RCVBUF,
&rcvbuf_size, sizeof(rcvbuf_size)) < 0) {
perror("setsockopt SO_RCVBUF");
@@ -651,31 +657,34 @@ int main(int argc, char **argv)
}
if (log) {
time_t currtime;
struct tm now;
char fname[83]; /* suggested by -Wformat-overflow= */
if (!logname) {
time_t currtime;
struct tm now;
if (time(&currtime) == (time_t)-1) {
perror("time");
return 1;
if (time(&currtime) == (time_t)-1) {
perror("time");
return 1;
}
localtime_r(&currtime, &now);
snprintf(fname, sizeof(fname), "candump-%04d-%02d-%02d_%02d%02d%02d.log",
now.tm_year + 1900,
now.tm_mon + 1,
now.tm_mday,
now.tm_hour,
now.tm_min,
now.tm_sec);
logname = fname;
}
localtime_r(&currtime, &now);
sprintf(fname, "candump-%04d-%02d-%02d_%02d%02d%02d.log",
now.tm_year + 1900,
now.tm_mon + 1,
now.tm_mday,
now.tm_hour,
now.tm_min,
now.tm_sec);
if (silent != SILENT_ON)
fprintf(stderr, "Warning: Console output active while logging!\n");
fprintf(stderr, "Enabling Logfile '%s'\n", fname);
fprintf(stderr, "Enabling Logfile '%s'\n", logname);
logfile = fopen(fname, "w");
logfile = fopen(logname, "w");
if (!logfile) {
perror("logfile");
return 1;
@@ -697,6 +706,12 @@ int main(int argc, char **argv)
continue;
}
/* handle timeout */
if (!num_events && timeout_ms >= 0) {
running = 0;
continue;
}
for (i = 0; i < num_events; i++) { /* check waiting CAN RAW sockets */
struct if_info* obj = events_pending[i].data.ptr;
int idx;
@@ -738,7 +753,6 @@ int main(int argc, char **argv)
if (cmsg->cmsg_type == SO_TIMESTAMP) {
memcpy(&tv, CMSG_DATA(cmsg), sizeof(tv));
} else if (cmsg->cmsg_type == SO_TIMESTAMPING) {
struct timespec *stamp = (struct timespec *)CMSG_DATA(cmsg);
/*
@@ -749,22 +763,22 @@ int main(int argc, char **argv)
* linux/Documentation/networking/timestamping.txt
*/
tv.tv_sec = stamp[2].tv_sec;
tv.tv_usec = stamp[2].tv_nsec/1000;
} else if (cmsg->cmsg_type == SO_RXQ_OVFL)
tv.tv_usec = stamp[2].tv_nsec / 1000;
} else if (cmsg->cmsg_type == SO_RXQ_OVFL) {
memcpy(&obj->dropcnt, CMSG_DATA(cmsg), sizeof(__u32));
}
}
/* check for (unlikely) dropped frames on this specific socket */
if (obj->dropcnt != obj->last_dropcnt) {
__u32 frames = obj->dropcnt - obj->last_dropcnt;
if (silent != SILENT_ON)
printf("DROPCOUNT: dropped %d CAN frame%s on '%s' socket (total drops %d)\n",
printf("DROPCOUNT: dropped %u CAN frame%s on '%s' socket (total drops %u)\n",
frames, (frames > 1)?"s":"", devname[idx], obj->dropcnt);
if (log)
fprintf(logfile, "DROPCOUNT: dropped %d CAN frame%s on '%s' socket (total drops %d)\n",
fprintf(logfile, "DROPCOUNT: dropped %u CAN frame%s on '%s' socket (total drops %u)\n",
frames, (frames > 1)?"s":"", devname[idx], obj->dropcnt);
obj->last_dropcnt = obj->dropcnt;
@@ -794,7 +808,7 @@ int main(int argc, char **argv)
extra_info);
}
if ((logfrmt) && (silent == SILENT_OFF)){
if ((logfrmt) && (silent == SILENT_OFF)) {
char buf[CL_CFSZ]; /* max length */
/* print CAN frame in log file style to stdout */
@@ -807,7 +821,7 @@ int main(int argc, char **argv)
goto out_fflush; /* no other output to stdout */
}
if (silent != SILENT_OFF){
if (silent != SILENT_OFF) {
if (silent == SILENT_ANI) {
printf("%c\b", anichar[silentani %= MAXANI]);
silentani++;
@@ -821,7 +835,6 @@ int main(int argc, char **argv)
printf("%*s", max_devname_len, devname[idx]);
if (extra_msg_info) {
if (msg.msg_flags & MSG_DONTROUTE)
printf (" TX %s", extra_m_info[frame.flags & 3]);
else
+200 -59
View File
@@ -4,6 +4,7 @@
*
* (C) 2009 by Vladislav Gribov, IXXAT Automation GmbH, <gribov@ixxat.de>
* (C) 2009 Wolfgang Grandegger <wg@grandegger.com>
* (C) 2021 Jean Gressmann, IAV GmbH, <jean.steven.gressmann@iav.de>
*
* 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
@@ -39,7 +40,8 @@
#include <linux/can.h>
#include <linux/can/raw.h>
#define CAN_MSG_ID 0x77
#define CAN_MSG_ID_PING 0x77
#define CAN_MSG_ID_PONG 0x78
#define CAN_MSG_LEN 8
#define CAN_MSG_COUNT 50
#define CAN_MSG_WAIT 27
@@ -50,6 +52,13 @@ static int sockfd;
static int test_loops;
static int exit_sig;
static int inflight_count = CAN_MSG_COUNT;
static canid_t can_id_ping = CAN_MSG_ID_PING;
static canid_t can_id_pong = CAN_MSG_ID_PONG;
static int has_pong_id = 0;
static int is_can_fd = 0;
static int bit_rate_switch = 0;
static int msg_len = CAN_MSG_LEN;
static int is_extended_frame_format = 0;
static void print_usage(char *prg)
{
@@ -58,11 +67,18 @@ static void print_usage(char *prg)
"Usage: %s [options] <can-interface>\n"
"\n"
"Options:\n"
" -b (enable CAN FD Bit Rate Switch)\n"
" -d (use CAN FD frames instead of classic CAN)\n"
" -e (use 29-bit extended frame format instead of classic 11-bit one)\n"
" -f COUNT (number of frames in flight, default: %d)\n"
" -g (generate messages)\n"
" -i ID (CAN ID to use for frames to DUT (ping), default %x)\n"
" -l COUNT (test loop count)\n"
" -o ID (CAN ID to use for frames to host (pong), default %x)\n"
" -s SIZE (frame payload size in bytes)\n"
" -v (low verbosity)\n"
" -vv (high verbosity)\n"
" -x (ignore other frames on bus)\n"
"\n"
"With the option '-g' CAN messages are generated and checked\n"
"on <can-interface>, otherwise all messages received on the\n"
@@ -74,56 +90,70 @@ static void print_usage(char *prg)
"%s -v can0\n"
"\ton Host:\n"
"%s -g -v can2\n",
prg, prg, CAN_MSG_COUNT, prg, prg);
prg, prg, CAN_MSG_COUNT, CAN_MSG_ID_PING, CAN_MSG_ID_PONG, prg, prg);
exit(1);
}
static void print_frame(const struct can_frame *frame, int inc)
static void print_frame(canid_t id, const uint8_t *data, int dlc, int inc_data)
{
int i;
printf("%04x: ", frame->can_id + inc);
if (frame->can_id & CAN_RTR_FLAG) {
printf("%04x: ", id);
if (id & CAN_RTR_FLAG) {
printf("remote request");
} else {
printf("[%d]", frame->can_dlc);
for (i = 0; i < frame->can_dlc; i++)
printf(" %02x", (uint8_t)(frame->data[i] + inc));
printf("[%d]", dlc);
for (i = 0; i < dlc; i++)
printf(" %02x", (uint8_t)(data[i] + inc_data));
}
printf("\n");
}
static void print_compare(const struct can_frame *exp, const struct can_frame *rec, int inc)
static void print_compare(
canid_t exp_id,
const uint8_t *exp_data,
uint8_t exp_dlc,
canid_t rec_id,
const uint8_t *rec_data,
uint8_t rec_dlc,
int inc)
{
printf("expected: ");
print_frame(exp, inc);
print_frame(exp_id, exp_data, exp_dlc, inc);
printf("received: ");
print_frame(rec, 0);
print_frame(rec_id, rec_data, rec_dlc, 0);
}
static void compare_frame(struct can_frame *exp, struct can_frame *rec, int inc)
static int compare_frame(const struct canfd_frame *exp, const struct canfd_frame *rec, int inc)
{
int i;
int i, err = 0;
const canid_t expected_can_id = inc ? can_id_pong : can_id_ping;
if (rec->can_id != exp->can_id + inc) {
if (rec->can_id != expected_can_id) {
printf("Message ID mismatch!\n");
print_compare(exp, rec, inc);
print_compare(expected_can_id, exp->data, exp->len,
rec->can_id, rec->data, rec->len, inc);
running = 0;
} else if (rec->can_dlc != exp->can_dlc) {
err = -1;
} else if (rec->len != exp->len) {
printf("Message length mismatch!\n");
print_compare(exp, rec, inc);
print_compare(expected_can_id, exp->data, exp->len,
rec->can_id, rec->data, rec->len, inc);
running = 0;
err = -1;
} else {
for (i = 0; i < rec->can_dlc; i++) {
for (i = 0; i < rec->len; i++) {
if (rec->data[i] != (uint8_t)(exp->data[i] + inc)) {
printf("Databyte %x mismatch!\n", i);
print_compare(exp,
rec, inc);
print_compare(expected_can_id, exp->data, exp->len,
rec->can_id, rec->data, rec->len, inc);
running = 0;
err = -1;
}
}
}
return err;
}
static void millisleep(int msecs)
@@ -160,29 +190,41 @@ static void signal_handler(int signo)
exit_sig = signo;
}
static int recv_frame(struct can_frame *frame)
static int recv_frame(struct canfd_frame *frame)
{
int ret;
ssize_t ret, len;
ret = recv(sockfd, frame, sizeof(*frame), 0);
if (ret != sizeof(*frame)) {
if (is_can_fd)
len = sizeof(struct canfd_frame);
else
len = sizeof(struct can_frame);
ret = recv(sockfd, frame, len, 0);
if (ret != len) {
if (ret < 0)
perror("recv failed");
else
fprintf(stderr, "recv returned %d", ret);
fprintf(stderr, "recv returned %zd", ret);
return -1;
}
return 0;
}
static int send_frame(struct can_frame *frame)
static int send_frame(struct canfd_frame *frame)
{
int ret;
ssize_t ret, len;
while ((ret = send(sockfd, frame, sizeof(*frame), 0))
!= sizeof(*frame)) {
if (is_can_fd)
len = sizeof(struct canfd_frame);
else
len = sizeof(struct can_frame);
if (bit_rate_switch)
frame->flags |= CANFD_BRS;
while ((ret = send(sockfd, frame, len, 0)) != len) {
if (ret >= 0) {
fprintf(stderr, "send returned %d", ret);
fprintf(stderr, "send returned %zd", ret);
return -1;
}
if (errno != ENOBUFS) {
@@ -197,25 +239,25 @@ static int send_frame(struct can_frame *frame)
return 0;
}
static int check_frame(const struct can_frame *frame)
static int check_frame(const struct canfd_frame *frame)
{
int err = 0;
int i;
if (frame->can_id != CAN_MSG_ID) {
printf("unexpected Message ID 0x%04x!\n", frame->can_id);
if (frame->can_id != can_id_ping) {
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);
if (frame->len != msg_len) {
printf("Unexpected Message length %d!\n", frame->len);
err = -1;
}
for (i = 1; i < frame->can_dlc; i++) {
for (i = 1; i < frame->len; i++) {
if (frame->data[i] != (uint8_t)(frame->data[i-1] + 1)) {
printf("Frame inconsistent!\n");
print_frame(frame, 0);
print_frame(frame->can_id, frame->data, frame->len, 0);
err = -1;
goto out;
}
@@ -225,19 +267,24 @@ static int check_frame(const struct can_frame *frame)
return err;
}
static void inc_frame(struct can_frame *frame)
static void inc_frame(struct canfd_frame *frame)
{
int i;
frame->can_id++;
for (i = 0; i < frame->can_dlc; i++)
if (has_pong_id)
frame->can_id = can_id_pong;
else
frame->can_id++;
for (i = 0; i < frame->len; i++)
frame->data[i]++;
}
static int can_echo_dut(void)
{
unsigned int frame_count = 0;
struct can_frame frame;
struct canfd_frame frame;
int err = 0;
while (running) {
if (recv_frame(&frame))
@@ -246,10 +293,10 @@ static int can_echo_dut(void)
if (verbose == 1) {
echo_progress(frame.data[0]);
} else if (verbose > 1) {
print_frame(&frame, 0);
print_frame(frame.can_id, frame.data, frame.len, 0);
}
check_frame(&frame);
err = check_frame(&frame);
inc_frame(&frame);
if (send_frame(&frame))
return -1;
@@ -264,14 +311,14 @@ static int can_echo_dut(void)
}
}
return 0;
return err;
}
static int can_echo_gen(void)
{
struct can_frame *tx_frames;
struct canfd_frame *tx_frames;
int *recv_tx;
struct can_frame rx_frame;
struct canfd_frame rx_frame;
unsigned char counter = 0;
int send_pos = 0, recv_rx_pos = 0, recv_tx_pos = 0, unprocessed = 0, loops = 0;
int err = 0;
@@ -290,11 +337,11 @@ static int can_echo_gen(void)
while (running) {
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;
tx_frames[send_pos].len = msg_len;
tx_frames[send_pos].can_id = can_id_ping;
recv_tx[send_pos] = 0;
for (i = 0; i < CAN_MSG_LEN; i++)
for (i = 0; i < msg_len; i++)
tx_frames[send_pos].data[i] = counter + i;
if (send_frame(&tx_frames[send_pos])) {
err = -1;
@@ -320,11 +367,11 @@ static int can_echo_gen(void)
}
if (verbose > 1)
print_frame(&rx_frame, 0);
print_frame(rx_frame.can_id, rx_frame.data, rx_frame.len, 0);
/* own frame */
if (rx_frame.can_id == CAN_MSG_ID) {
compare_frame(&tx_frames[recv_tx_pos], &rx_frame, 0);
if (rx_frame.can_id == can_id_ping) {
err = 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)
@@ -334,11 +381,11 @@ static int can_echo_gen(void)
if (!recv_tx[recv_rx_pos]) {
printf("RX before TX!\n");
print_frame(&rx_frame, 0);
print_frame(rx_frame.can_id, rx_frame.data, rx_frame.len, 0);
running = 0;
}
/* compare with expected */
compare_frame(&tx_frames[recv_rx_pos], &rx_frame, 1);
err = compare_frame(&tx_frames[recv_rx_pos], &rx_frame, 1);
recv_rx_pos++;
if (recv_rx_pos == inflight_count)
recv_rx_pos = 0;
@@ -368,14 +415,27 @@ 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;
int enable_socket_option = 1;
int filter = 0;
signal(SIGTERM, signal_handler);
signal(SIGHUP, signal_handler);
signal(SIGINT, signal_handler);
while ((opt = getopt(argc, argv, "f:gl:v?")) != -1) {
while ((opt = getopt(argc, argv, "bdef:gi:l:o:s:vx?")) != -1) {
switch (opt) {
case 'b':
bit_rate_switch = 1;
break;
case 'd':
is_can_fd = 1;
break;
case 'e':
is_extended_frame_format = 1;
break;
case 'f':
inflight_count = atoi(optarg);
break;
@@ -384,14 +444,31 @@ int main(int argc, char *argv[])
echo_gen = 1;
break;
case 'i':
can_id_ping = strtoul(optarg, NULL, 16);
break;
case 'l':
test_loops = atoi(optarg);
break;
case 'o':
can_id_pong = strtoul(optarg, NULL, 16);
has_pong_id = 1;
break;
case 's':
msg_len = atoi(optarg);
break;
case 'v':
verbose++;
break;
case 'x':
filter = 1;
break;
case '?':
default:
print_usage(basename(argv[0]));
@@ -399,6 +476,39 @@ int main(int argc, char *argv[])
}
}
/* BRS can be enabled only if CAN FD is enabled */
if (bit_rate_switch && !is_can_fd) {
printf("Bit rate switch (-b) needs CAN FD (-d) to be enabled\n");
return 1;
}
/* Make sure the message length is valid */
if (msg_len <= 0) {
printf("Message length must > 0\n");
return 1;
}
if (is_can_fd) {
if (msg_len > CANFD_MAX_DLEN) {
printf("Message length must be <= %d bytes for CAN FD\n", CANFD_MAX_DLEN);
return 1;
}
} else {
if (msg_len > CAN_MAX_DLEN) {
printf("Message length must be <= %d bytes for CAN 2.0B\n", CAN_MAX_DLEN);
return 1;
}
}
if (is_extended_frame_format) {
can_id_ping &= CAN_EFF_MASK;
can_id_ping |= CAN_EFF_FLAG;
can_id_pong &= CAN_EFF_MASK;
can_id_pong |= CAN_EFF_FLAG;
} else {
can_id_ping &= CAN_SFF_MASK;
can_id_pong &= CAN_SFF_MASK;
}
if ((argc - optind) != 1)
print_usage(basename(argv[0]));
intf_name = argv[optind];
@@ -413,8 +523,16 @@ int main(int argc, char *argv[])
if (echo_gen) {
if (setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,
&recv_own_msgs, sizeof(recv_own_msgs)) == -1) {
perror("setsockopt");
&enable_socket_option, sizeof(enable_socket_option)) == -1) {
perror("setsockopt CAN_RAW_RECV_OWN_MSGS");
return 1;
}
}
if (is_can_fd) {
if (setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_FD_FRAMES,
&enable_socket_option, sizeof(enable_socket_option)) == -1) {
perror("setsockopt CAN_RAW_FD_FRAMES");
return 1;
}
}
@@ -433,6 +551,29 @@ int main(int argc, char *argv[])
return 1;
}
if (!has_pong_id)
can_id_pong = can_id_ping + 1;
if (filter) {
const struct can_filter filters[] = {
{
.can_id = can_id_ping,
.can_mask = CAN_EFF_FLAG | CAN_RTR_FLAG | CAN_SFF_MASK,
},
{
.can_id = can_id_pong,
.can_mask = CAN_EFF_FLAG | CAN_RTR_FLAG | CAN_SFF_MASK,
},
};
if (setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_FILTER, filters,
sizeof(struct can_filter) * (1 + echo_gen))) {
perror("setsockopt()");
close(sockfd);
return 1;
}
}
if (echo_gen)
err = can_echo_gen();
else
+442 -127
View File
@@ -2,6 +2,8 @@
/*
* cangen.c - CAN frames generator
*
* Copyright (c) 2022 Pengutronix,
* Marc Kleine-Budde <kernel@pengutronix.de>
* Copyright (c) 2002-2007 Volkswagen Group Electronic Research
* All rights reserved.
*
@@ -44,9 +46,12 @@
#include <ctype.h>
#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>
@@ -63,66 +68,135 @@
#include <linux/can.h>
#include <linux/can/raw.h>
#include <linux/net_tstamp.h>
#include "lib.h"
#define DEFAULT_GAP 200 /* ms */
#define DEFAULT_BURST_COUNT 1
#define DEFAULT_SO_MARK_VAL 1
#define MODE_RANDOM 0
#define MODE_INCREMENT 1
#define MODE_FIX 2
#define MODE_RANDOM_EVEN 3
#define MODE_RANDOM_ODD 4
#define MODE_RANDOM 0
#define MODE_INCREMENT 1
#define MODE_FIX 2
#define MODE_RANDOM_EVEN 3
#define MODE_RANDOM_ODD 4
#define MODE_RANDOM_FIX 5
#define NIBBLE_H 1
#define NIBBLE_L 2
#define CHAR_RANDOM 'x'
extern int optind, opterr, optopt;
static volatile int running = 1;
static unsigned long long enobufs_count;
static bool ignore_enobufs;
static bool use_so_txtime;
void print_usage(char *prg)
static int clockid = CLOCK_TAI;
static int clock_nanosleep_flags;
static struct timespec ts, ts_gap;
static int so_mark_val = DEFAULT_SO_MARK_VAL;
#define NSEC_PER_SEC 1000000000LL
static struct timespec timespec_normalise(struct timespec ts)
{
while (ts.tv_nsec >= NSEC_PER_SEC) {
++(ts.tv_sec);
ts.tv_nsec -= NSEC_PER_SEC;
}
while (ts.tv_nsec <= -NSEC_PER_SEC) {
--(ts.tv_sec);
ts.tv_nsec += NSEC_PER_SEC;
}
if (ts.tv_nsec < 0) {
/*
* Negative nanoseconds isn't valid according to
* POSIX. Decrement tv_sec and roll tv_nsec over.
*/
--(ts.tv_sec);
ts.tv_nsec = (NSEC_PER_SEC + ts.tv_nsec);
}
return ts;
}
static struct timespec timespec_add(struct timespec ts1, struct timespec ts2)
{
/*
* Normalize inputs to prevent tv_nsec rollover if
* whole-second values are packed in it.
*/
ts1 = timespec_normalise(ts1);
ts2 = timespec_normalise(ts2);
ts1.tv_sec += ts2.tv_sec;
ts1.tv_nsec += ts2.tv_nsec;
return timespec_normalise(ts1);
}
struct timespec double_to_timespec(double s)
{
struct timespec ts = {
.tv_sec = s,
.tv_nsec = (s - (long)(s)) * NSEC_PER_SEC,
};
return timespec_normalise(ts);
}
static struct timespec ns_to_timespec(int64_t ns)
{
struct timespec ts = {
.tv_sec = ns / NSEC_PER_SEC,
.tv_nsec = ns % NSEC_PER_SEC,
};
return timespec_normalise(ts);
}
static void print_usage(char *prg)
{
fprintf(stderr, "%s - CAN frames generator.\n\n", prg);
fprintf(stderr, "Usage: %s [options] <CAN interface>\n", prg);
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, " -g <ms> (gap in milli seconds - default: %d ms)\n", DEFAULT_GAP);
fprintf(stderr, " -a (use absolute time for gap)\n");
fprintf(stderr, " -t (use SO_TXTIME)\n");
fprintf(stderr, " --start <ns> (start time (UTC nanoseconds))\n");
fprintf(stderr, " --mark <id> (set SO_MARK to <id>, default %u)\n", DEFAULT_SO_MARK_VAL);
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, " -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 (generate RTR frames)\n");
fprintf(stderr, " -8 (allow DLC values greater then 8 for Classic CAN 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)"
" generation mode - see below)\n");
fprintf(stderr, " -D <mode> (CAN data (payload)"
" generation mode - see below)\n");
fprintf(stderr, " -p <timeout> (poll on -ENOBUFS to write frames"
" with <timeout> ms)\n");
fprintf(stderr, " -n <count> (terminate after <count> CAN frames "
"- default infinite)\n");
fprintf(stderr, " -i (ignore -ENOBUFS return values on"
" write() syscalls)\n");
fprintf(stderr, " -x (disable local loopback of "
"generated CAN frames)\n");
fprintf(stderr, " -c <count> (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, " -I <mode> (CAN ID generation mode - see below)\n");
fprintf(stderr, " -L <mode> (CAN data length code (dlc) generation mode - see below)\n");
fprintf(stderr, " -D <mode> (CAN data (payload) generation mode - see below)\n");
fprintf(stderr, " -p <timeout> (poll on -ENOBUFS to write frames with <timeout> ms)\n");
fprintf(stderr, " -n <count> (terminate after <count> CAN frames - default infinite)\n");
fprintf(stderr, " -i (ignore -ENOBUFS return values on write() syscalls)\n");
fprintf(stderr, " -x (disable local loopback of generated CAN frames)\n");
fprintf(stderr, " -c <count> (number of messages to send in burst, default %u)\n", DEFAULT_BURST_COUNT);
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, " 'e' => random values, even ID\n");
fprintf(stderr, " 'o' => random values, odd ID\n");
fprintf(stderr, " 'i' => increment values\n");
fprintf(stderr, " <value> => fixed value (in hexadecimal for -I and -D)\n\n");
fprintf(stderr, "When incrementing the CAN data the data length code "
"minimum is set to 1.\n");
fprintf(stderr, " <value> => fixed value (in hexadecimal for -I and -D)\n");
fprintf(stderr, " => nibbles written as '%c' are randomized (only -D)\n\n", CHAR_RANDOM);
fprintf(stderr, "The gap value (in milliseconds) may have decimal places, e.g. '-g 4.73'\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\n", prg);
@@ -131,6 +205,10 @@ void print_usage(char *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 -D 11%c%c3344DEADBEEF -L 8\n", prg, CHAR_RANDOM, CHAR_RANDOM);
fprintf(stderr, "\t(fixed CAN data payload where 2. byte is randomized, fixed length)\n");
fprintf(stderr, "%s vcan0 -I 555 -D CCCCCCCCCCCCCCCC -L 8 -g 3.75\n", prg);
fprintf(stderr, "\t(generate a fix busload without bit-stuffing effects)\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);
@@ -139,17 +217,227 @@ void print_usage(char *prg)
fprintf(stderr, "\t(my favourite default :)\n\n");
}
void sigterm(int signo)
static void sigterm(int signo)
{
running = 0;
}
static int setsockopt_txtime(int fd)
{
const struct sock_txtime so_txtime_val = {
.clockid = clockid,
.flags = SOF_TXTIME_REPORT_ERRORS,
};
struct sock_txtime so_txtime_val_read;
int so_mark_val_read;
socklen_t vallen;
int ret;
/* SO_TXTIME */
ret = setsockopt(fd, SOL_SOCKET, SO_TXTIME,
&so_txtime_val, sizeof(so_txtime_val));
if (ret) {
int err = errno;
perror("setsockopt() SO_TXTIME");
if (err == EPERM)
fprintf(stderr, "Run with CAP_NET_ADMIN or as root.\n");
return -err;
};
vallen = sizeof(so_txtime_val_read);
ret = getsockopt(fd, SOL_SOCKET, SO_TXTIME,
&so_txtime_val_read, &vallen);
if (ret) {
perror("getsockopt() SO_TXTIME");
return -errno;
};
if (vallen != sizeof(so_txtime_val) ||
memcmp(&so_txtime_val, &so_txtime_val_read, vallen)) {
perror("getsockopt() SO_TXTIME: mismatch");
return -EINVAL;
}
/* SO_MARK */
ret = setsockopt(fd, SOL_SOCKET, SO_MARK, &so_mark_val, sizeof(so_mark_val));
if (ret) {
int err = errno;
perror("setsockopt() SO_MARK");
if (err == EPERM)
fprintf(stderr, "Run with CAP_NET_ADMIN or as root.\n");
return -err;
};
vallen = sizeof(so_mark_val_read);
ret = getsockopt(fd, SOL_SOCKET, SO_MARK,
&so_mark_val_read, &vallen);
if (ret) {
perror("getsockopt() SO_MARK");
return -errno;
};
if (vallen != sizeof(so_mark_val) ||
memcmp(&so_mark_val, &so_mark_val_read, vallen)) {
perror("getsockopt() SO_MARK: mismatch");
return -EINVAL;
}
return 0;
}
static int do_send_one(int fd, void *buf, size_t len, int timeout)
{
uint8_t control[CMSG_SPACE(sizeof(uint64_t))] = { 0 };
struct iovec iov = {
.iov_base = buf,
.iov_len = len,
};
struct msghdr msg = {
.msg_iov = &iov,
.msg_iovlen = 1,
};
ssize_t nbytes;
int ret;
if (use_so_txtime) {
struct cmsghdr *cm;
uint64_t tdeliver;
msg.msg_control = control;
msg.msg_controllen = sizeof(control);
tdeliver = ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec;
ts = timespec_add(ts, ts_gap);
cm = CMSG_FIRSTHDR(&msg);
cm->cmsg_level = SOL_SOCKET;
cm->cmsg_type = SCM_TXTIME;
cm->cmsg_len = CMSG_LEN(sizeof(tdeliver));
memcpy(CMSG_DATA(cm), &tdeliver, sizeof(tdeliver));
}
resend:
nbytes = sendmsg(fd, &msg, 0);
if (nbytes < 0) {
ret = -errno;
if (ret != -ENOBUFS) {
perror("write");
return ret;
}
if (!ignore_enobufs && !timeout) {
perror("write");
return ret;
}
if (timeout) {
struct pollfd fds = {
.fd = fd,
.events = POLLOUT,
};
/* wait for the write socket (with timeout) */
ret = poll(&fds, 1, timeout);
if (ret == 0 || (ret == -1 && errno != EINTR)) {
ret = -errno;
perror("poll");
return ret;
}
goto resend;
} else {
enobufs_count++;
}
} else if (nbytes < (ssize_t)len) {
fprintf(stderr, "write: incomplete CAN frame\n");
return -EINVAL;
}
return 0;
}
static int setup_time(void)
{
int ret;
if (use_so_txtime) {
/* start time is defined */
if (ts.tv_sec || ts.tv_nsec)
return 0;
/* start time is now .... */
ret = clock_gettime(clockid, &ts);
if (ret) {
perror("clock_gettime");
return ret;
}
/* ... + gap */
ts = timespec_add(ts, ts_gap);
return 0;
}
if (ts.tv_sec || ts.tv_nsec) {
ret = clock_nanosleep(clockid, TIMER_ABSTIME, &ts, NULL);
if (ret != 0 && ret != EINTR) {
perror("clock_nanosleep");
return ret;
}
} else if (clock_nanosleep_flags == TIMER_ABSTIME) {
ret = clock_gettime(clockid, &ts);
if (ret)
perror("clock_gettime");
return ret;
}
if (clock_nanosleep_flags != TIMER_ABSTIME)
ts = ts_gap;
return 0;
}
enum {
OPT_MARK = UCHAR_MAX + 1,
OPT_START = UCHAR_MAX + 2,
};
/*
* Search for CHAR_RANDOM in dataoptarg, save its position, replace it with 0.
* Return 1 if at least one CHAR_RANDOM found.
*/
static int parse_dataoptarg(char *dataoptarg, unsigned char *rand_position)
{
int mode_format_selected = MODE_FIX;
int arglen = strlen(dataoptarg);
/* Mark nibbles with * as fuzzable */
for (int i = 0; i < CANFD_MAX_DLEN && i < arglen / 2; i++) {
if (optarg[2 * i] == CHAR_RANDOM) {
optarg[2 * i] = '0';
rand_position[i] += NIBBLE_H;
mode_format_selected = MODE_RANDOM_FIX;
}
if (optarg[2 * i + 1] == CHAR_RANDOM) {
optarg[2 * i + 1] = '0';
rand_position[i] += NIBBLE_L;
mode_format_selected = MODE_RANDOM_FIX;
}
}
return mode_format_selected;
}
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;
@@ -169,20 +457,19 @@ int main(int argc, char **argv)
int incdlc = 0;
unsigned long rnd;
unsigned char fixdata[CANFD_MAX_DLEN];
unsigned char rand_position[CANFD_MAX_DLEN] = {0};
int opt;
int s; /* socket */
struct pollfd fds;
struct sockaddr_can addr;
struct sockaddr_can addr = { 0 };
static struct canfd_frame frame;
struct can_frame *ccf = (struct can_frame *)&frame;
int nbytes;
int i;
struct ifreq ifr;
struct timespec ts;
struct timeval now;
int ret;
/* set seed value for pseudo random numbers */
gettimeofday(&now, NULL);
@@ -192,17 +479,39 @@ int main(int argc, char **argv)
signal(SIGHUP, sigterm);
signal(SIGINT, sigterm);
while ((opt = getopt(argc, argv, "ig:ebEfmI:L:D:xp:n:c:vR8h?")) != -1) {
switch (opt) {
const struct option long_options[] = {
{ "mark", required_argument, 0, OPT_MARK, },
{ "start", required_argument, 0, OPT_START, },
{ 0, 0, 0, 0 },
};
case 'i':
ignore_enobufs = 1;
break;
while ((opt = getopt_long(argc, argv, "g:atefbER8mI:L:D:p:n:ixc:vh?", long_options, NULL)) != -1) {
switch (opt) {
case 'g':
gap = strtod(optarg, NULL);
break;
case 'a':
clock_nanosleep_flags = TIMER_ABSTIME;
break;
case 't':
clock_nanosleep_flags = TIMER_ABSTIME;
use_so_txtime = true;
break;
case OPT_START: {
int64_t start_time_ns;
start_time_ns = strtoll(optarg, NULL, 0);
ts = ns_to_timespec(start_time_ns);
break;
}
case OPT_MARK:
so_mark_val = strtoul(optarg, NULL, 0);
break;
case 'e':
extended = 1;
break;
@@ -221,6 +530,14 @@ int main(int argc, char **argv)
canfd = 1;
break;
case 'R':
rtr_frame = 1;
break;
case '8':
len8_dlc = 1;
break;
case 'm':
mix = 1;
canfd = 1; /* to switch the socket into CAN FD mode */
@@ -258,34 +575,15 @@ int main(int argc, char **argv)
} else if (optarg[0] == 'i') {
data_mode = MODE_INCREMENT;
} else {
data_mode = MODE_FIX;
data_mode = parse_dataoptarg(optarg, rand_position);
if (hexstring2data(optarg, fixdata, CANFD_MAX_DLEN)) {
printf ("wrong fix data definition\n");
printf("wrong fix data definition\n");
return 1;
}
}
break;
case 'c':
burst_count = strtoul(optarg, NULL, 10);
break;
case 'v':
verbose++;
break;
case 'x':
loopback_disable = 1;
break;
case 'R':
rtr_frame = 1;
break;
case '8':
len8_dlc = 1;
break;
case 'p':
polltimeout = strtoul(optarg, NULL, 10);
break;
@@ -298,12 +596,27 @@ int main(int argc, char **argv)
}
break;
case 'i':
ignore_enobufs = true;
break;
case 'x':
loopback_disable = 1;
break;
case 'c':
burst_count = strtoul(optarg, NULL, 10);
break;
case 'v':
verbose++;
break;
case '?':
case 'h':
default:
print_usage(basename(argv[0]));
return 1;
break;
}
}
@@ -312,13 +625,11 @@ int main(int argc, char **argv)
return 1;
}
ts.tv_sec = gap / 1000;
ts.tv_nsec = (long)(((long long)(gap * 1000000)) % 1000000000LL);
ts_gap = double_to_timespec(gap / 1000);
/* recognize obviously missing commandline option */
if (id_mode == MODE_FIX && frame.can_id > 0x7FF && !extended) {
printf("The given CAN-ID is greater than 0x7FF and "
"the '-e' option is not set.\n");
printf("The given CAN-ID is greater than 0x7FF and the '-e' option is not set.\n");
return 1;
}
@@ -327,7 +638,8 @@ int main(int argc, char **argv)
return 1;
}
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (s < 0) {
perror("socket");
return 1;
}
@@ -341,21 +653,23 @@ int main(int argc, char **argv)
}
addr.can_ifindex = ifr.ifr_ifindex;
/* disable default receive filter on this RAW socket */
/* This is obsolete as we do not read from the socket at all, but for */
/* this reason we can remove the receive list in the Kernel to save a */
/* little (really a very little!) CPU usage. */
/*
* disable default receive filter on this RAW socket
* This is obsolete as we do not read from the socket at all, but for
* this reason we can remove the receive list in the Kernel to save a
* little (really a very little!) CPU usage.
*/
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
if (loopback_disable) {
int loopback = 0;
const int loopback = 0;
setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
&loopback, sizeof(loopback));
}
if (canfd) {
int enable_canfd = 1;
const int enable_canfd = 1;
/* check if the frame fits into the CAN netdevice */
if (ioctl(s, SIOCGIFMTU, &ifr) < 0) {
@@ -369,7 +683,7 @@ int main(int argc, char **argv)
}
/* interface is ok - try to switch the socket into CAN FD mode */
if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &enable_canfd, sizeof(enable_canfd))){
if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &enable_canfd, sizeof(enable_canfd))) {
printf("error when enabling CAN FD support\n");
return 1;
}
@@ -395,18 +709,23 @@ int main(int argc, char **argv)
return 1;
}
if (polltimeout) {
fds.fd = s;
fds.events = POLLOUT;
if (use_so_txtime) {
ret = setsockopt_txtime(s);
if (ret)
return 1;
}
ret = setup_time();
if (ret)
return 1;
while (running) {
frame.flags = 0;
if (count && (--count == 0))
running = 0;
if (canfd){
if (canfd) {
mtu = CANFD_MTU;
maxdlen = CANFD_MAX_DLEN;
if (brs)
@@ -435,7 +754,6 @@ int main(int argc, char **argv)
frame.can_id |= CAN_RTR_FLAG;
if (dlc_mode == MODE_RANDOM) {
if (canfd)
frame.len = can_fd_dlc2len(random() & 0xF);
else {
@@ -457,7 +775,6 @@ int main(int argc, char **argv)
frame.len = 1; /* min dlc value for incr. data */
if (data_mode == MODE_RANDOM) {
rnd = random();
memcpy(&frame.data[0], &rnd, 4);
rnd = random();
@@ -471,6 +788,20 @@ int main(int argc, char **argv)
}
}
if (data_mode == MODE_RANDOM_FIX) {
memcpy(frame.data, fixdata, CANFD_MAX_DLEN);
for (int i = 0; i < frame.len; i++) {
if (rand_position[i] == (NIBBLE_H | NIBBLE_L)) {
frame.data[i] = random();
} else if (rand_position[i] == NIBBLE_H) {
frame.data[i] = (frame.data[i] & 0x0f) | (random() & 0xf0);
} else if (rand_position[i] == NIBBLE_L) {
frame.data[i] = (frame.data[i] & 0xf0) | (random() & 0x0f);
}
}
}
if (data_mode == MODE_FIX)
memcpy(frame.data, fixdata, CANFD_MAX_DLEN);
@@ -478,55 +809,40 @@ int main(int argc, char **argv)
if (frame.len < maxdlen)
memset(&frame.data[frame.len], 0, maxdlen - frame.len);
if (verbose) {
if (!use_so_txtime &&
(ts.tv_sec || ts.tv_nsec) &&
burst_sent_count >= burst_count) {
if (clock_nanosleep_flags == TIMER_ABSTIME)
ts = timespec_add(ts, ts_gap);
ret = clock_nanosleep(clockid, clock_nanosleep_flags, &ts, NULL);
if (ret != 0 && ret != EINTR) {
perror("clock_nanosleep");
return 1;
}
}
if (verbose) {
printf(" %s ", argv[optind]);
if (verbose > 1)
fprint_long_canframe(stdout, &frame, "\n", (verbose > 2)?1:0, maxdlen);
fprint_long_canframe(stdout, &frame, "\n", (verbose > 2) ? 1 : 0, maxdlen);
else
fprint_canframe(stdout, &frame, "\n", 1, maxdlen);
}
resend:
nbytes = write(s, &frame, mtu);
if (nbytes < 0) {
if (errno != ENOBUFS) {
perror("write");
return 1;
}
if (!ignore_enobufs && !polltimeout) {
perror("write");
return 1;
}
if (polltimeout) {
/* wait for the write socket (with timeout) */
if (poll(&fds, 1, polltimeout) < 0) {
perror("poll");
return 1;
}
goto resend;
} else
enobufs_count++;
} else if (nbytes < mtu) {
fprintf(stderr, "write: incomplete CAN frame\n");
ret = do_send_one(s, &frame, mtu, polltimeout);
if (ret)
return 1;
}
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;
burst_sent_count++;
if (id_mode == MODE_INCREMENT)
frame.can_id++;
if (dlc_mode == MODE_INCREMENT) {
incdlc++;
incdlc %= CAN_MAX_RAW_DLC + 1;
@@ -547,22 +863,21 @@ resend:
}
if (data_mode == MODE_INCREMENT) {
incdata++;
for (i=0; i<8 ;i++)
frame.data[i] = (incdata >> i*8) & 0xFFULL;
for (i = 0; i < 8; i++)
frame.data[i] = incdata >> i * 8;
}
if (mix) {
i = random();
extended = i&1;
canfd = i&2;
extended = i & 1;
canfd = i & 2;
if (canfd) {
brs = i&4;
esi = i&8;
brs = i & 4;
esi = i & 8;
}
rtr_frame = ((i&24) == 24); /* reduce RTR frames to 1/4 */
rtr_frame = ((i & 24) == 24); /* reduce RTR frames to 1/4 */
}
}
+9 -1
View File
@@ -743,10 +743,18 @@ int main(int argc, char **argv)
case 's':
src_ifindex = if_nametoindex(optarg);
if (!src_ifindex) {
perror("src if_nametoindex");
exit(1);
}
break;
case 'd':
dst_ifindex = if_nametoindex(optarg);
if (!dst_ifindex) {
perror("dst if_nametoindex");
exit(1);
}
break;
case 'X':
@@ -766,7 +774,7 @@ int main(int argc, char **argv)
break;
case 'u':
uid = strtoul(optarg, (char **)NULL, 16);
uid = strtoul(optarg, NULL, 16);
break;
case 'l':
+4 -8
View File
@@ -145,9 +145,7 @@ int idx2dindex(int ifidx, int socket)
strcpy(devname[i], ifr.ifr_name);
#ifdef DEBUG
printf("new index %d (%s)\n", i, devname[i]);
#endif
pr_debug("new index %d (%s)\n", i, devname[i]);
return i;
}
@@ -310,11 +308,9 @@ int main(int argc, char **argv)
for (i=0; i<currmax; i++) {
#ifdef DEBUG
printf("open %d '%s' m%08X v%08X i%d e%d.\n",
i, argv[optind+i], mask[i], value[i],
inv_filter[i], err_mask[i]);
#endif
pr_debug("open %d '%s' m%08X v%08X i%d e%d.\n",
i, argv[optind+i], mask[i], value[i],
inv_filter[i], err_mask[i]);
if ((s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
perror("socket");
+15 -1
View File
@@ -89,6 +89,8 @@ void print_usage(char *prg)
"send frames immediately)\n");
fprintf(stderr, " -i (interactive - wait "
"for ENTER key to process next frame)\n");
fprintf(stderr, " -n <count> (terminate after "
"processing <count> CAN frames)\n");
fprintf(stderr, " -g <ms> (gap in milli "
"seconds - default: %d ms)\n", DEFAULT_GAP);
fprintf(stderr, " -s <s> (skip gaps in "
@@ -247,6 +249,7 @@ int main(int argc, char **argv)
unsigned long gap = DEFAULT_GAP;
int use_timestamps = 1;
int interactive = 0; /* wait for ENTER keypress to process next frame */
int count = 0; /* end replay after sending count frames. 0 = disabled */
static int verbose, opt, delay_loops;
static unsigned long skipgap;
static int loopback_disable = 0;
@@ -257,7 +260,7 @@ int main(int argc, char **argv)
int eof, txmtu, i, j;
char *fret;
while ((opt = getopt(argc, argv, "I:l:tig:s:xv?")) != -1) {
while ((opt = getopt(argc, argv, "I:l:tin:g:s:xv?")) != -1) {
switch (opt) {
case 'I':
infile = fopen(optarg, "r");
@@ -285,6 +288,14 @@ int main(int argc, char **argv)
interactive = 1;
break;
case 'n':
count = atoi(optarg);
if (count < 1) {
print_usage(basename(argv[0]));
exit(1);
}
break;
case 'g':
gap = strtoul(optarg, NULL, 10);
break;
@@ -476,6 +487,9 @@ int main(int argc, char **argv)
else
fprint_long_canframe(stdout, &frame, "\n", CANLIB_VIEW_INDENT_SFF, CANFD_MAX_DLEN);
}
if (count && (--count == 0))
goto out;
}
/* read next non-comment frame from logfile */
+13 -9
View File
@@ -92,7 +92,7 @@ static void do_receive()
unsigned int sequence_wrap = 0;
uint32_t sequence_mask = 0xff;
uint32_t sequence_rx = 0;
uint32_t sequence_delta = 0;
uint8_t sequence_delta = 0;
uint32_t sequence = 0;
unsigned int overflow_old = 0;
can_err_mask_t err_mask = CAN_ERR_MASK;
@@ -143,7 +143,7 @@ static void do_receive()
sequence = sequence_rx;
}
sequence_delta = (sequence_rx - sequence) & sequence_mask;
sequence_delta = sequence_rx - (uint8_t)sequence;
if (sequence_delta) {
struct cmsghdr *cmsg;
uint32_t overflow = 0;
@@ -163,12 +163,16 @@ static void do_receive()
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);
"sequence CNT: 0x%07x RX: 0x%02x expected: 0x%02x missing: %4u skt overflow delta: %4u absolute: %4u hw - skt: %5d incident: %4u %s%s\n",
sequence, sequence_rx, /* CNT, RX */
sequence & sequence_mask, sequence_delta, /* expected, missing */
overflow_delta, overflow, /* skb overflow delta, absolute */
sequence_delta - overflow_delta, /* hw - skb */
drop_count, /* incident */
overflow_delta ? "[SOCKET]" : "",
overflow_delta != sequence_delta ?
((overflow_delta - sequence_delta > 0 && (overflow_delta - sequence_delta) & 0xff) ?
"[HARDWARE]" : "[HARDWARE?]") : "");
if (drop_count == drop_until_quit)
exit(EXIT_FAILURE);
@@ -216,7 +220,7 @@ static void do_send()
}
err = poll(fds, 1, 1000);
if (err == -1 && errno != -EINTR) {
if (err == 0 || (err == -1 && errno != -EINTR)) {
perror("poll()");
exit(EXIT_FAILURE);
}
+230 -116
View File
@@ -69,9 +69,16 @@
#include "terminal.h"
#define SETFNAME "sniffset."
#define SETFDFNAME "sniffset_fd."
#define FNAME_MAX_LEN 40
#define ANYDEV "any"
#define MAX_SLOTS 2048
#define CANFD_OFF 0 /* set to OFF */
#define CANFD_ON 1 /* set to ON */
#define CANFD_AUTO 2 /* unspecified => check for first received frame */
/* flags */
#define ENABLE 1 /* by filter or user */
@@ -98,16 +105,19 @@
#define LDL " | " /* long delimiter */
#define SDL "|" /* short delimiter for binary on 80 chars terminal */
#define CC_SEP '#' /* interface name separator for Classical CAN */
#define FD_SEP '*' /* interface name separator for CAN FD */
static struct snif {
int flags;
long hold;
long timeout;
struct timeval laststamp;
struct timeval currstamp;
struct can_frame last;
struct can_frame current;
struct can_frame marker;
struct can_frame notch;
struct canfd_frame last;
struct canfd_frame current;
struct canfd_frame marker;
struct canfd_frame notch;
} sniftab[MAX_SLOTS];
extern int optind, opterr, optopt;
@@ -116,14 +126,18 @@ static int idx;
static int running = 1;
static int clearscreen = 1;
static int print_eff;
static int print_ascii = 1;
static int notch;
static int max_dlen = CAN_MAX_DLEN;
static long timeout = TIMEOUT;
static long hold = HOLD;
static long loop = LOOP;
static long canfd_mode = CANFD_AUTO;
static unsigned char binary;
static unsigned char binary8;
static unsigned char binary_gap;
static unsigned char color;
static unsigned char name_sep = CC_SEP;
static char *interface;
static char *vdl = LDL; /* variable delimiter */
static char *ldl = LDL; /* long delimiter */
@@ -132,7 +146,7 @@ void print_snifline(int slot);
int handle_keyb(void);
int handle_frame(int fd, long currcms);
int handle_timeo(long currcms);
void writesettings(char* name);
int writesettings(char* name);
int readsettings(char* name);
int sniftab_index(canid_t id);
@@ -166,6 +180,7 @@ void print_usage(char *prg)
" 8<ENTER> - toggle binary / HEX-ASCII output (small for EFF on 80 chars)\n"
" B<ENTER> - toggle binary with gap / HEX-ASCII output (exceeds 80 chars!)\n"
" c<ENTER> - toggle color mode\n"
" @<ENTER> - toggle ASCII output (disabled for CAN FD by default)\n"
" <SPACE><ENTER> - force a clear screen\n"
" #<ENTER> - notch currently marked/changed bits (can be used repeatedly)\n"
" *<ENTER> - clear notched marked\n"
@@ -215,6 +230,7 @@ void print_usage(char *prg)
fprintf(stderr, " -8 (start with binary mode - for EFF on 80 chars)\n");
fprintf(stderr, " -B (start with binary mode with gap - exceeds 80 chars!)\n");
fprintf(stderr, " -c (color changes)\n");
fprintf(stderr, " -f <mode> (CAN FD mode: 0 = OFF, 1 = ON, 2 = auto detect, default: %d)\n", CANFD_AUTO);
fprintf(stderr, " -t <time> (timeout for ID display [x10ms] default: %d, 0 = OFF)\n", TIMEOUT);
fprintf(stderr, " -h <time> (hold marker on changes [x10ms] default: %d)\n", HOLD);
fprintf(stderr, " -l <time> (loop time (display) [x10ms] default: %d)\n", LOOP);
@@ -236,7 +252,7 @@ int main(int argc, char **argv)
long currcms = 0;
long lastcms = 0;
unsigned char quiet = 0;
int opt, ret;
int opt, ret = 0;
struct timeval timeo, start_tv, tv;
struct sockaddr_can addr;
int i;
@@ -248,7 +264,7 @@ int main(int argc, char **argv)
for (i = 0; i < MAX_SLOTS ;i++) /* default: enable all slots */
do_set(i, ENABLE);
while ((opt = getopt(argc, argv, "r:t:h:l:qeb8Bc?")) != -1) {
while ((opt = getopt(argc, argv, "r:t:h:l:f:qeb8Bc?")) != -1) {
switch (opt) {
case 'r':
if (readsettings(optarg) < 0) {
@@ -269,6 +285,12 @@ int main(int argc, char **argv)
sscanf(optarg, "%ld", &loop);
break;
case 'f':
sscanf(optarg, "%ld", &canfd_mode);
if ((canfd_mode != CANFD_ON) && (canfd_mode != CANFD_OFF))
canfd_mode = CANFD_AUTO;
break;
case 'q':
quiet = 1;
break;
@@ -313,7 +335,7 @@ int main(int argc, char **argv)
print_usage(basename(argv[0]));
exit(0);
}
if (quiet)
for (i = 0; i < MAX_SLOTS; i++)
do_clr(i, ENABLE);
@@ -332,15 +354,38 @@ int main(int argc, char **argv)
}
addr.can_family = AF_CAN;
addr.can_ifindex = 0; /* 'any' CAN interface */
if (strcmp(ANYDEV, argv[optind]) != 0)
/* check for specific CAN interface */
if (strcmp(ANYDEV, argv[optind]) != 0) {
addr.can_ifindex = if_nametoindex(argv[optind]);
else
addr.can_ifindex = 0; /* any can interface */
if (!addr.can_ifindex) {
perror("if_nametoindex");
return 1;
}
}
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("connect");
return 1;
/* enable CAN FD if not disabled by command line option */
if (canfd_mode != CANFD_OFF) {
const int enable_canfd = 1;
if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES,
&enable_canfd, sizeof(enable_canfd))){
printf("error when enabling CAN FD support\n");
return 1;
}
/* might be changed in CANFD_AUTO mode */
max_dlen = CANFD_MAX_DLEN;
name_sep = FD_SEP;
print_ascii = 0; /* don't print ASCII for CAN FD by default */
}
ret = bind(s, (struct sockaddr *)&addr, sizeof(addr));
if (ret < 0) {
perror("bind");
close(s);
return ret;
}
gettimeofday(&start_tv, NULL);
@@ -357,11 +402,13 @@ int main(int argc, char **argv)
timeo.tv_sec = 0;
timeo.tv_usec = 10000 * loop;
if ((ret = select(s+1, &rdfs, NULL, NULL, &timeo)) < 0) {
ret = select(s+1, &rdfs, NULL, NULL, &timeo);
if (ret < 0) {
//perror("select");
running = 0;
continue;
}
} else
ret = 0;
gettimeofday(&tv, NULL);
currcms = (tv.tv_sec - start_tv.tv_sec) * 100 + (tv.tv_usec / 10000);
@@ -381,7 +428,7 @@ int main(int argc, char **argv)
printf("%s", CSR_SHOW); /* show cursor */
close(s);
return 0;
return ret;
}
void do_modify_sniftab(unsigned int value, unsigned int mask, char cmd)
@@ -436,7 +483,7 @@ int handle_keyb(void)
}
/* check for single SFF/EFF CAN ID length */
if (!((clen == 3) || (clen == 8)))
if (clen != 3 && clen != 8)
break;
/* enable/disable single SFF/EFF CAN ID */
@@ -480,17 +527,24 @@ int handle_keyb(void)
break;
case 'w' :
writesettings(&cmd[1]);
if (writesettings(&cmd[1]))
return 0;
break;
case 'r' :
readsettings(&cmd[1]); /* don't care about success */
if (readsettings(&cmd[1]) < 0)
return 0;
break;
case 'q' :
running = 0;
break;
case '@' :
/* toggle ASCII output */
print_ascii ^= 1;
break;
case 'B' :
binary_gap = 1;
switchvdl(LDL);
@@ -534,7 +588,7 @@ int handle_keyb(void)
case '*' :
for (i = 0; i < idx; i++)
memset(&sniftab[i].notch.data, 0, 8);
memset(&sniftab[i].notch.data, 0, max_dlen);
break;
default:
@@ -551,18 +605,40 @@ int handle_frame(int fd, long currcms)
bool rx_changed = false;
bool run_qsort = false;
int nbytes, i, pos;
struct can_frame cf;
struct canfd_frame cf;
if ((nbytes = read(fd, &cf, sizeof(cf))) < 0) {
nbytes = read(fd, &cf, sizeof(cf));
if (nbytes < 0) {
perror("raw read");
return 0; /* quit */
}
if (nbytes != CAN_MTU) {
if ((nbytes != CAN_MTU) && (nbytes != CANFD_MTU)) {
printf("received strange frame data length %d!\n", nbytes);
return 0; /* quit */
}
/* CAN FD auto mode: switch based on first reception */
if (canfd_mode == CANFD_AUTO) {
if (nbytes == CAN_MTU) {
canfd_mode = CANFD_OFF;
/* change back auto defaults for Classical CAN */
max_dlen = CAN_MAX_DLEN;
name_sep = CC_SEP;
print_ascii = 1;
} else {
canfd_mode = CANFD_ON;
}
}
/* filter for Classical CAN */
if ((canfd_mode == CANFD_OFF) && (nbytes == CANFD_MTU))
return 1; /* skip handling */
/* filter for CAN FD */
if ((canfd_mode == CANFD_ON) && (nbytes == CAN_MTU))
return 1; /* skip handling */
if (!print_eff && (cf.can_id & CAN_EFF_FLAG)) {
print_eff = 1;
clearscreen = 1;
@@ -571,20 +647,19 @@ int handle_frame(int fd, long currcms)
pos = sniftab_index(cf.can_id);
if (pos < 0) {
/* CAN ID not existing */
if (idx < MAX_SLOTS) {
/* assign new slot */
pos = idx++;
rx_changed = true;
run_qsort = true;
} else {
if (idx >= MAX_SLOTS) {
/* informative exit */
perror("number of different CAN IDs exceeded MAX_SLOTS");
return 0; /* quit */
}
/* assign new slot */
pos = idx++;
rx_changed = true;
run_qsort = true;
}
else {
if (cf.can_dlc == sniftab[pos].current.can_dlc)
for (i = 0; i < cf.can_dlc; i++) {
if (cf.len == sniftab[pos].current.len)
for (i = 0; i < cf.len; i++) {
if (cf.data[i] != sniftab[pos].current.data[i] ) {
rx_changed = true;
break;
@@ -603,7 +678,7 @@ int handle_frame(int fd, long currcms)
ioctl(fd, SIOCGSTAMP, &sniftab[pos].currstamp);
sniftab[pos].current = cf;
for (i = 0; i < 8; i++)
for (i = 0; i < max_dlen; i++)
sniftab[pos].marker.data[i] |= sniftab[pos].current.data[i] ^ sniftab[pos].last.data[i];
sniftab[pos].timeout = (timeout)?(currcms + timeout):0;
@@ -629,11 +704,11 @@ int handle_timeo(long currcms)
if (clearscreen) {
if (print_eff)
printf("%s%sXX|ms%s-- ID --%sdata ... < %s # l=%ld h=%ld t=%ld slots=%d >",
CLR_SCREEN, CSR_HOME, vdl, vdl, interface, loop, hold, timeout, idx);
printf("%s%sXX|ms%s-- ID --%sdata ... < %s %c l=%ld h=%ld t=%ld slots=%d >",
CLR_SCREEN, CSR_HOME, vdl, vdl, interface, name_sep, loop, hold, timeout, idx);
else
printf("%s%sXX|ms%sID %sdata ... < %s # l=%ld h=%ld t=%ld slots=%d >",
CLR_SCREEN, CSR_HOME, ldl, ldl, interface, loop, hold, timeout, idx);
printf("%s%sXX|ms%sID %sdata ... < %s %c l=%ld h=%ld t=%ld slots=%d >",
CLR_SCREEN, CSR_HOME, ldl, ldl, interface, name_sep, loop, hold, timeout, idx);
force_redraw = 1;
clearscreen = 0;
@@ -641,7 +716,7 @@ int handle_timeo(long currcms)
if (notch) {
for (i = 0; i < idx; i++) {
for (j = 0; j < 8; j++)
for (j = 0; j < max_dlen; j++)
sniftab[i].notch.data[j] |= sniftab[i].marker.data[j];
}
notch = 0;
@@ -660,7 +735,7 @@ int handle_timeo(long currcms)
do_clr(i, UPDATE);
}
else if ((sniftab[i].hold) && (sniftab[i].hold < currcms)) {
memset(&sniftab[i].marker.data, 0, 8);
memset(&sniftab[i].marker.data, 0, max_dlen);
print_snifline(i);
sniftab[i].hold = 0; /* disable update by hold */
}
@@ -684,7 +759,7 @@ void print_snifline(int slot)
{
long diffsec = sniftab[slot].currstamp.tv_sec - sniftab[slot].laststamp.tv_sec;
long diffusec = sniftab[slot].currstamp.tv_usec - sniftab[slot].laststamp.tv_usec;
int dlc_diff = sniftab[slot].last.can_dlc - sniftab[slot].current.can_dlc;
int dlc_diff = sniftab[slot].last.len - sniftab[slot].current.len;
canid_t cid = sniftab[slot].current.can_id;
int i,j;
@@ -705,7 +780,7 @@ void print_snifline(int slot)
printf("%02ld%03ld%s%03X%s", diffsec, diffusec/1000, ldl, cid & CAN_SFF_MASK, ldl);
if (binary) {
for (i = 0; i < sniftab[slot].current.can_dlc; i++) {
for (i = 0; i < sniftab[slot].current.len; i++) {
for (j=7; j >= 0; j--) {
if ((color) && (sniftab[slot].marker.data[i] & 1<<j) &&
(!(sniftab[slot].notch.data[i] & 1<<j)))
@@ -724,7 +799,7 @@ void print_snifline(int slot)
}
/*
* when the can_dlc decreased (dlc_diff > 0),
* when the len decreased (dlc_diff > 0),
* we need to blank the former data printout
*/
for (i = 0; i < dlc_diff; i++) {
@@ -732,111 +807,150 @@ void print_snifline(int slot)
if (binary_gap)
putchar(' ');
}
}
else {
for (i = 0; i < sniftab[slot].current.can_dlc; i++)
} else { /* not binary -> hex data and ASCII output */
for (i = 0; i < sniftab[slot].current.len; i++)
if ((color) && (sniftab[slot].marker.data[i] & ~sniftab[slot].notch.data[i]))
printf("%s%02X%s ", ATTCOLOR, sniftab[slot].current.data[i], ATTRESET);
else
printf("%02X ", sniftab[slot].current.data[i]);
if (sniftab[slot].current.can_dlc < 8)
printf("%*s", (8 - sniftab[slot].current.can_dlc) * 3, "");
if (print_ascii) {
/* jump to common start for ASCII output */
if (sniftab[slot].current.len < max_dlen)
printf("%*s", (max_dlen - sniftab[slot].current.len) * 3, "");
for (i = 0; i<sniftab[slot].current.can_dlc; i++)
if ((sniftab[slot].current.data[i] > 0x1F) &&
(sniftab[slot].current.data[i] < 0x7F))
if ((color) && (sniftab[slot].marker.data[i] & ~sniftab[slot].notch.data[i]))
printf("%s%c%s", ATTCOLOR, sniftab[slot].current.data[i], ATTRESET);
for (i = 0; i < sniftab[slot].current.len; i++)
if ((sniftab[slot].current.data[i] > 0x1F) &&
(sniftab[slot].current.data[i] < 0x7F))
if ((color) && (sniftab[slot].marker.data[i] & ~sniftab[slot].notch.data[i]))
printf("%s%c%s", ATTCOLOR, sniftab[slot].current.data[i], ATTRESET);
else
putchar(sniftab[slot].current.data[i]);
else
putchar(sniftab[slot].current.data[i]);
else
putchar('.');
putchar('.');
/*
* when the can_dlc decreased (dlc_diff > 0),
* we need to blank the former data printout
*/
for (i = 0; i < dlc_diff; i++)
putchar(' ');
/*
* when the len decreased (dlc_diff > 0),
* we need to blank the former data printout
*/
for (i = 0; i < dlc_diff; i++)
putchar(' ');
} else {
/*
* when the len decreased (dlc_diff > 0),
* we need to blank the former data printout
*/
for (i = 0; i < dlc_diff; i++)
printf(" ");
}
}
putchar('\n');
memset(&sniftab[slot].marker.data, 0, 8);
memset(&sniftab[slot].marker.data, 0, max_dlen);
}
void writesettings(char* name)
int writesettings(char* name)
{
int fd;
char fname[30] = SETFNAME;
char fname[FNAME_MAX_LEN + 1];
int i,j;
char buf[13]= {0};
strncat(fname, name, 29 - strlen(fname));
fd = open(fname, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
if (fd > 0) {
for (i = 0; i < idx ;i++) {
sprintf(buf, "<%08X>%c.", sniftab[i].current.can_id, (is_set(i, ENABLE))?'1':'0');
if (write(fd, buf, 12) < 0)
perror("write");
for (j = 0; j < 8 ; j++) {
sprintf(buf, "%02X", sniftab[i].notch.data[j]);
if (write(fd, buf, 2) < 0)
perror("write");
}
if (write(fd, "\n", 1) < 0)
perror("write");
/* 12 + 16 + 1 = 29 bytes per entry */
}
close(fd);
if (canfd_mode == CANFD_OFF)
strcpy(fname, SETFNAME);
else if (canfd_mode == CANFD_ON)
strcpy(fname, SETFDFNAME);
else {
printf("writesettings failed due to unspecified CAN FD mode\n");
return 1;
}
else
strncat(fname, name, FNAME_MAX_LEN - strlen(fname));
fd = open(fname, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
if (fd <= 0) {
printf("unable to write setting file '%s'!\n", fname);
return 1;
}
for (i = 0; i < idx ;i++) {
sprintf(buf, "<%08X>%c.", sniftab[i].current.can_id, (is_set(i, ENABLE))?'1':'0');
if (write(fd, buf, 12) < 0) {
perror("write");
return 1;
}
for (j = 0; j < max_dlen ; j++) {
sprintf(buf, "%02X", sniftab[i].notch.data[j]);
if (write(fd, buf, 2) < 0) {
perror("write");
return 1;
}
}
if (write(fd, "\n", 1) < 0) {
perror("write");
return 1;
}
/* Classical CAN: 12 + 16 + 1 = 29 bytes per entry */
/* CAN FD: 12 + 128 + 1 = 141 bytes per entry */
}
close(fd);
return 0;
}
int readsettings(char* name)
{
int fd;
char fname[30] = SETFNAME;
char buf[30] = {0};
char fname[FNAME_MAX_LEN + 1];
char buf[142] = {0};
int entrylen;
int j;
bool done = false;
strncat(fname, name, 29 - strlen(fname));
fd = open(fname, O_RDONLY);
if (fd > 0) {
idx = 0;
while (!done) {
if (read(fd, &buf, 29) == 29) {
unsigned long id = strtoul(&buf[1], (char **)NULL, 16);
sniftab[idx].current.can_id = id;
if (buf[10] & 1)
do_set(idx, ENABLE);
else
do_clr(idx, ENABLE);
for (j = 7; j >= 0 ; j--) {
sniftab[idx].notch.data[j] =
(__u8) strtoul(&buf[2*j+12], (char **)NULL, 16) & 0xFF;
buf[2*j+12] = 0; /* cut off each time */
}
if (++idx >= MAX_SLOTS)
break;
}
else
done = true;
}
close(fd);
}
else
if (canfd_mode == CANFD_OFF) {
entrylen = 29;
strcpy(fname, SETFNAME);
} else if (canfd_mode == CANFD_ON) {
entrylen = 141;
strcpy(fname, SETFDFNAME);
} else {
printf("readsettings failed due to unspecified CAN FD mode\n");
return -1;
}
strncat(fname, name, FNAME_MAX_LEN - strlen(fname));
fd = open(fname, O_RDONLY);
if (fd <= 0) {
return -1;
}
idx = 0;
while (!done) {
if (read(fd, &buf, entrylen) != entrylen) {
done = true;
continue;
}
unsigned long id = strtoul(&buf[1], NULL, 16);
sniftab[idx].current.can_id = id;
if (buf[10] & 1)
do_set(idx, ENABLE);
else
do_clr(idx, ENABLE);
for (j = max_dlen - 1; j >= 0 ; j--) {
sniftab[idx].notch.data[j] =
(__u8) strtoul(&buf[2*j+12], NULL, 16) & 0xFF;
buf[2*j+12] = 0; /* cut off each time */
}
if (++idx >= MAX_SLOTS)
break;
}
close(fd);
return idx;
}
+25 -6
View File
@@ -9,6 +9,9 @@ AC_CONFIG_AUX_DIR([config/autoconf])
AC_CANONICAL_BUILD
AC_CANONICAL_HOST
# If possible, enable extensions to Posix
AC_USE_SYSTEM_EXTENSIONS
#AM_MAINTAINER_MODE
CFLAGS="${CFLAGS} -Wall"
@@ -77,21 +80,37 @@ AC_CHECK_FUNCS([ \
AC_SEARCH_LIBS([clock_nanosleep], [rt])
AC_CHECK_DECL(SO_RXQ_OVFL,,
[AC_DEFINE([SO_RXQ_OVFL], [40], [SO_RXQ_OVFL])]
[AC_DEFINE([SO_RXQ_OVFL], [40], [SO_RXQ_OVFL])],
[[#include <linux/net.h>]]
)
AC_CHECK_DECL(PF_CAN,,
[AC_DEFINE([PF_CAN], [29], [PF_CAN])]
[AC_DEFINE([PF_CAN], [29], [PF_CAN])],
[[#include <net/if.h>]]
)
AC_CHECK_DECL(AF_CAN,,
[AC_DEFINE([AF_CAN], [PF_CAN], [AF_CAN])]
[AC_DEFINE([AF_CAN], [PF_CAN], [AF_CAN])],
[[#include <net/if.h>]]
)
AC_CHECK_DECL(N_SLCAN,,
[AC_DEFINE([N_SLCAN], [17], [N_SLCAN])]
[AC_DEFINE([N_SLCAN], [17], [N_SLCAN])],
[[#include <linux/tty.h>]]
)
AC_CHECK_DECL(SCM_TIMESTAMPING_OPT_STATS,,
[AC_DEFINE([SCM_TIMESTAMPING_OPT_STATS], [54], [SCM_TIMESTAMPING_OPT_STATS])]
[AC_DEFINE([SCM_TIMESTAMPING_OPT_STATS], [54], [SCM_TIMESTAMPING_OPT_STATS])],
[[#include <linux/net.h>]]
)
AC_CHECK_DECL(CLOCK_TAI,,
[AC_DEFINE([CLOCK_TAI], [11], [CLOCK_TAI])],
[[#include <time.h>]]
)
AC_CHECK_DECL(SO_TXTIME,,
[AC_DEFINE([SO_TXTIME], [61], [SO_TXTIME])],
[[#include <sys/socket.h>]]
)
AC_CHECK_DECL(SCM_TXTIME,,
[AC_DEFINE([SCM_TXTIME], [SO_TXTIME], [SCM_TXTIME])],
[[#include <sys/socket.h>]]
)
AC_DEFINE(_GNU_SOURCE)
#
+53 -2
View File
@@ -48,6 +48,7 @@
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/stddef.h> /* for offsetof */
/* controller area network (CAN) kernel definitions */
@@ -60,6 +61,7 @@
#define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */
#define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */
#define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */
#define CANXL_PRIO_MASK CAN_SFF_MASK /* 11 bit priority mask */
/*
* Controller Area Network Identifier structure
@@ -73,6 +75,7 @@ typedef __u32 canid_t;
#define CAN_SFF_ID_BITS 11
#define CAN_EFF_ID_BITS 29
#define CANXL_PRIO_BITS CAN_SFF_ID_BITS
/*
* Controller Area Network Error Message Frame Mask structure
@@ -91,6 +94,16 @@ typedef __u32 can_err_mask_t;
#define CANFD_MAX_DLC 15
#define CANFD_MAX_DLEN 64
/*
* CAN XL payload length and DLC definitions according to ISO 11898-1
* CAN XL DLC ranges from 0 .. 2047 => data length from 1 .. 2048 byte
*/
#define CANXL_MIN_DLC 0
#define CANXL_MAX_DLC 2047
#define CANXL_MAX_DLC_MASK 0x07FF
#define CANXL_MIN_DLEN 1
#define CANXL_MAX_DLEN 2048
/**
* struct can_frame - Classical CAN frame structure (aka CAN 2.0B)
* @can_id: CAN ID of the frame and CAN_*_FLAG flags, see canid_t definition
@@ -141,8 +154,8 @@ struct can_frame {
* When this is done the former differentiation via CAN_MTU / CANFD_MTU gets
* lost. CANFD_FDF allows programmers to mark CAN FD frames in the case of
* using struct canfd_frame for mixed CAN / CAN FD content (dual use).
* N.B. the Kernel APIs do NOT provide mixed CAN / CAN FD content inside of
* struct canfd_frame therefore the CANFD_FDF flag is disregarded by Linux.
* Since the introduction of CAN XL the CANFD_FDF flag is set in all CAN FD
* frame structures provided by the CAN subsystem of the Linux kernel.
*/
#define CANFD_BRS 0x01 /* bit rate switch (second bitrate for payload data) */
#define CANFD_ESI 0x02 /* error state indicator of the transmitting node */
@@ -166,8 +179,46 @@ struct canfd_frame {
__u8 data[CANFD_MAX_DLEN] __attribute__((aligned(8)));
};
/*
* defined bits for canxl_frame.flags
*
* The canxl_frame.flags element contains two bits CANXL_XLF and CANXL_SEC
* and shares the relative position of the struct can[fd]_frame.len element.
* The CANXL_XLF bit ALWAYS needs to be set to indicate a valid CAN XL frame.
* As a side effect setting this bit intentionally breaks the length checks
* for Classical CAN and CAN FD frames.
*
* Undefined bits in canxl_frame.flags are reserved and shall be set to zero.
*/
#define CANXL_XLF 0x80 /* mandatory CAN XL frame flag (must always be set!) */
#define CANXL_SEC 0x01 /* Simple Extended Content (security/segmentation) */
/**
* struct canxl_frame - CAN with e'X'tended frame 'L'ength frame structure
* @prio: 11 bit arbitration priority with zero'ed CAN_*_FLAG flags
* @flags: additional flags for CAN XL
* @sdt: SDU (service data unit) type
* @len: frame payload length in byte (CANXL_MIN_DLEN .. CANXL_MAX_DLEN)
* @af: acceptance field
* @data: CAN XL frame payload (CANXL_MIN_DLEN .. CANXL_MAX_DLEN byte)
*
* @prio shares the same position as @can_id from struct can[fd]_frame.
*/
struct canxl_frame {
canid_t prio; /* 11 bit priority for arbitration (canid_t) */
__u8 flags; /* additional flags for CAN XL */
__u8 sdt; /* SDU (service data unit) type */
__u16 len; /* frame payload length in byte */
__u32 af; /* acceptance field */
__u8 data[CANXL_MAX_DLEN];
};
#define CAN_MTU (sizeof(struct can_frame))
#define CANFD_MTU (sizeof(struct canfd_frame))
#define CANXL_MTU (sizeof(struct canxl_frame))
#define CANXL_HDR_SIZE (offsetof(struct canxl_frame, data))
#define CANXL_MIN_MTU (CANXL_HDR_SIZE + 64)
#define CANXL_MAX_MTU CANXL_MTU
/* particular protocols of the protocol family PF_CAN */
#define CAN_RAW 1 /* RAW sockets */
+1 -1
View File
@@ -71,7 +71,7 @@ struct bcm_msg_head {
struct bcm_timeval ival1, ival2;
canid_t can_id;
__u32 nframes;
struct can_frame frames[0];
struct can_frame frames[];
};
enum {
+19 -1
View File
@@ -57,6 +57,8 @@
#define CAN_ERR_BUSOFF 0x00000040U /* bus off */
#define CAN_ERR_BUSERROR 0x00000080U /* bus error (may flood!) */
#define CAN_ERR_RESTARTED 0x00000100U /* controller restarted */
#define CAN_ERR_CNT 0x00000200U /* TX error counter / data[6] */
/* RX error counter / data[7] */
/* arbitration lost in bit ... / data[0] */
#define CAN_ERR_LOSTARB_UNSPEC 0x00 /* unspecified */
@@ -120,6 +122,22 @@
#define CAN_ERR_TRX_CANL_SHORT_TO_GND 0x70 /* 0111 0000 */
#define CAN_ERR_TRX_CANL_SHORT_TO_CANH 0x80 /* 1000 0000 */
/* controller specific additional information / data[5..7] */
/* data[5] is reserved (do not use) */
/* TX error counter / data[6] */
/* RX error counter / data[7] */
/* CAN state thresholds
*
* Error counter Error state
* -----------------------------------
* 0 - 95 Error-active
* 96 - 127 Error-warning
* 128 - 255 Error-passive
* 256 and greater Bus-off
*/
#define CAN_ERROR_WARNING_THRESHOLD 96
#define CAN_ERROR_PASSIVE_THRESHOLD 128
#define CAN_BUS_OFF_THRESHOLD 256
#endif /* _UAPI_CAN_ERROR_H */
+35 -18
View File
@@ -124,33 +124,30 @@ struct can_isotp_ll_options {
/* flags for isotp behaviour */
#define CAN_ISOTP_LISTEN_MODE 0x001 /* listen only (do not send FC) */
#define CAN_ISOTP_EXTEND_ADDR 0x002 /* enable extended addressing */
#define CAN_ISOTP_TX_PADDING 0x004 /* enable CAN frame padding tx path */
#define CAN_ISOTP_RX_PADDING 0x008 /* enable CAN frame padding rx path */
#define CAN_ISOTP_CHK_PAD_LEN 0x010 /* check received CAN frame padding */
#define CAN_ISOTP_CHK_PAD_DATA 0x020 /* check received CAN frame padding */
#define CAN_ISOTP_HALF_DUPLEX 0x040 /* half duplex error state handling */
#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 */
#define CAN_ISOTP_SF_BROADCAST 0x800 /* 1-to-N functional addressing */
#define CAN_ISOTP_LISTEN_MODE 0x0001 /* listen only (do not send FC) */
#define CAN_ISOTP_EXTEND_ADDR 0x0002 /* enable extended addressing */
#define CAN_ISOTP_TX_PADDING 0x0004 /* enable CAN frame padding tx path */
#define CAN_ISOTP_RX_PADDING 0x0008 /* enable CAN frame padding rx path */
#define CAN_ISOTP_CHK_PAD_LEN 0x0010 /* check received CAN frame padding */
#define CAN_ISOTP_CHK_PAD_DATA 0x0020 /* check received CAN frame padding */
#define CAN_ISOTP_HALF_DUPLEX 0x0040 /* half duplex error state handling */
#define CAN_ISOTP_FORCE_TXSTMIN 0x0080 /* ignore stmin from received FC */
#define CAN_ISOTP_FORCE_RXSTMIN 0x0100 /* ignore CFs depending on rx stmin */
#define CAN_ISOTP_RX_EXT_ADDR 0x0200 /* different rx extended addressing */
#define CAN_ISOTP_WAIT_TX_DONE 0x0400 /* wait for tx completion */
#define CAN_ISOTP_SF_BROADCAST 0x0800 /* 1-to-N functional addressing */
#define CAN_ISOTP_CF_BROADCAST 0x1000 /* 1-to-N transmission w/o FC */
/* default values */
/* protocol machine default values */
#define CAN_ISOTP_DEFAULT_FLAGS 0
#define CAN_ISOTP_DEFAULT_EXT_ADDRESS 0x00
#define CAN_ISOTP_DEFAULT_PAD_CONTENT 0xCC /* prevent bit-stuffing */
#define CAN_ISOTP_DEFAULT_FRAME_TXTIME 0
#define CAN_ISOTP_DEFAULT_FRAME_TXTIME 50000 /* 50 micro seconds */
#define CAN_ISOTP_DEFAULT_RECV_BS 0
#define CAN_ISOTP_DEFAULT_RECV_STMIN 0x00
#define CAN_ISOTP_DEFAULT_RECV_WFTMAX 0
#define CAN_ISOTP_DEFAULT_LL_MTU CAN_MTU
#define CAN_ISOTP_DEFAULT_LL_TX_DL CAN_MAX_DLEN
#define CAN_ISOTP_DEFAULT_LL_TX_FLAGS 0
/*
* Remark on CAN_ISOTP_DEFAULT_RECV_* values:
*
@@ -162,4 +159,24 @@ struct can_isotp_ll_options {
* consistency and copied directly into the flow control (FC) frame.
*/
/* link layer default values => make use of Classical CAN frames */
#define CAN_ISOTP_DEFAULT_LL_MTU CAN_MTU
#define CAN_ISOTP_DEFAULT_LL_TX_DL CAN_MAX_DLEN
#define CAN_ISOTP_DEFAULT_LL_TX_FLAGS 0
/*
* The CAN_ISOTP_DEFAULT_FRAME_TXTIME has become a non-zero value as
* it only makes sense for isotp implementation tests to run without
* a N_As value. As user space applications usually do not set the
* frame_txtime element of struct can_isotp_options the new in-kernel
* default is very likely overwritten with zero when the sockopt()
* CAN_ISOTP_OPTS is invoked.
* To make sure that a N_As value of zero is only set intentional the
* value '0' is now interpreted as 'do not change the current value'.
* When a frame_txtime of zero is required for testing purposes this
* CAN_ISOTP_FRAME_TXTIME_ZERO u32 value has to be set in frame_txtime.
*/
#define CAN_ISOTP_FRAME_TXTIME_ZERO 0xFFFFFFFF
#endif /* !_UAPI_CAN_ISOTP_H */
+9
View File
@@ -78,11 +78,20 @@ enum {
enum {
J1939_NLA_PAD,
J1939_NLA_BYTES_ACKED,
J1939_NLA_TOTAL_SIZE,
J1939_NLA_PGN,
J1939_NLA_SRC_NAME,
J1939_NLA_DEST_NAME,
J1939_NLA_SRC_ADDR,
J1939_NLA_DEST_ADDR,
};
enum {
J1939_EE_INFO_NONE,
J1939_EE_INFO_TX_ABORT,
J1939_EE_INFO_RX_RTS,
J1939_EE_INFO_RX_DPO,
J1939_EE_INFO_RX_ABORT,
};
struct j1939_filter {
+42 -2
View File
@@ -101,6 +101,8 @@ struct can_ctrlmode {
#define CAN_CTRLMODE_PRESUME_ACK 0x40 /* Ignore missing CAN ACKs */
#define CAN_CTRLMODE_FD_NON_ISO 0x80 /* CAN FD in non-ISO mode */
#define CAN_CTRLMODE_CC_LEN8_DLC 0x100 /* Classic CAN DLC option */
#define CAN_CTRLMODE_TDC_AUTO 0x200 /* CAN transiver automatically calculates TDCV */
#define CAN_CTRLMODE_TDC_MANUAL 0x400 /* TDCV is manually set up by user */
/*
* CAN device statistics
@@ -134,10 +136,48 @@ enum {
IFLA_CAN_BITRATE_CONST,
IFLA_CAN_DATA_BITRATE_CONST,
IFLA_CAN_BITRATE_MAX,
__IFLA_CAN_MAX
IFLA_CAN_TDC,
IFLA_CAN_CTRLMODE_EXT,
/* add new constants above here */
__IFLA_CAN_MAX,
IFLA_CAN_MAX = __IFLA_CAN_MAX - 1
};
#define IFLA_CAN_MAX (__IFLA_CAN_MAX - 1)
/*
* CAN FD Transmitter Delay Compensation (TDC)
*
* Please refer to struct can_tdc_const and can_tdc in
* include/linux/can/bittiming.h for further details.
*/
enum {
IFLA_CAN_TDC_UNSPEC,
IFLA_CAN_TDC_TDCV_MIN, /* u32 */
IFLA_CAN_TDC_TDCV_MAX, /* u32 */
IFLA_CAN_TDC_TDCO_MIN, /* u32 */
IFLA_CAN_TDC_TDCO_MAX, /* u32 */
IFLA_CAN_TDC_TDCF_MIN, /* u32 */
IFLA_CAN_TDC_TDCF_MAX, /* u32 */
IFLA_CAN_TDC_TDCV, /* u32 */
IFLA_CAN_TDC_TDCO, /* u32 */
IFLA_CAN_TDC_TDCF, /* u32 */
/* add new constants above here */
__IFLA_CAN_TDC,
IFLA_CAN_TDC_MAX = __IFLA_CAN_TDC - 1
};
/*
* IFLA_CAN_CTRLMODE_EXT nest: controller mode extended parameters
*/
enum {
IFLA_CAN_CTRLMODE_UNSPEC,
IFLA_CAN_CTRLMODE_SUPPORTED, /* u32 */
/* add new constants above here */
__IFLA_CAN_CTRLMODE,
IFLA_CAN_CTRLMODE_MAX = __IFLA_CAN_CTRLMODE - 1
};
/* u16 termination range: 1..65535 Ohms */
#define CAN_TERMINATION_DISABLED 0
+1
View File
@@ -62,6 +62,7 @@ enum {
CAN_RAW_RECV_OWN_MSGS, /* receive my own msgs (default:off) */
CAN_RAW_FD_FRAMES, /* allow CAN FD frames (default:off) */
CAN_RAW_JOIN_FILTERS, /* all filters must match to trigger */
CAN_RAW_XL_FRAMES, /* allow CAN XL frames (default:off) */
};
#endif /* !_UAPI_CAN_RAW_H */
+9 -5
View File
@@ -125,7 +125,7 @@ void print_uds_message(int service, int nrc)
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 0x84: service_name = "SecuredDataTransmission"; break;
case 0x85: service_name = "ControlDTCSetting"; break;
case 0x86: service_name = "ResponseOnEvent"; break;
case 0x87: service_name = "LinkControl"; break;
@@ -225,13 +225,13 @@ int main(int argc, char **argv)
while ((opt = getopt(argc, argv, "s:d:ax:X:ct:u?")) != -1) {
switch (opt) {
case 's':
src = strtoul(optarg, (char **)NULL, 16);
src = strtoul(optarg, NULL, 16);
if (strlen(optarg) > 7)
src |= CAN_EFF_FLAG;
break;
case 'd':
dst = strtoul(optarg, (char **)NULL, 16);
dst = strtoul(optarg, NULL, 16);
if (strlen(optarg) > 7)
dst |= CAN_EFF_FLAG;
break;
@@ -249,7 +249,7 @@ int main(int argc, char **argv)
if (!strncmp(optarg, "any", 3))
extany = 1;
else
extaddr = strtoul(optarg, (char **)NULL, 16) & 0xFF;
extaddr = strtoul(optarg, NULL, 16) & 0xFF;
break;
case 'X':
@@ -257,7 +257,7 @@ int main(int argc, char **argv)
if (!strncmp(optarg, "any", 3))
rx_extany = 1;
else
rx_extaddr = strtoul(optarg, (char **)NULL, 16) & 0xFF;
rx_extaddr = strtoul(optarg, NULL, 16) & 0xFF;
break;
case 't':
@@ -325,6 +325,10 @@ int main(int argc, char **argv)
addr.can_family = AF_CAN;
addr.can_ifindex = if_nametoindex(argv[optind]);
if (!addr.can_ifindex) {
perror("if_nametoindex");
return 1;
}
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind");
+8 -4
View File
@@ -121,25 +121,25 @@ int main(int argc, char **argv)
while ((opt = getopt(argc, argv, "s:d:x:X:?")) != -1) {
switch (opt) {
case 's':
src = strtoul(optarg, (char **)NULL, 16);
src = strtoul(optarg, NULL, 16);
if (strlen(optarg) > 7)
src |= CAN_EFF_FLAG;
break;
case 'd':
dst = strtoul(optarg, (char **)NULL, 16);
dst = strtoul(optarg, NULL, 16);
if (strlen(optarg) > 7)
dst |= CAN_EFF_FLAG;
break;
case 'x':
ext = 1;
extaddr = strtoul(optarg, (char **)NULL, 16) & 0xFF;
extaddr = strtoul(optarg, NULL, 16) & 0xFF;
break;
case 'X':
rx_ext = 1;
rx_extaddr = strtoul(optarg, (char **)NULL, 16) & 0xFF;
rx_extaddr = strtoul(optarg, NULL, 16) & 0xFF;
break;
case '?':
@@ -189,6 +189,10 @@ int main(int argc, char **argv)
addr.can_family = AF_CAN;
addr.can_ifindex = if_nametoindex(argv[optind]);
if (!addr.can_ifindex) {
perror("if_nametoindex");
return 1;
}
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind");
+11 -7
View File
@@ -57,7 +57,7 @@
#include <linux/can/isotp.h>
#define NO_CAN_ID 0xFFFFFFFFU
#define BUFSIZE 5000 /* size > 4095 to check socket API internal checks */
#define BUFSIZE 67000 /* size > 66000 to check socket API internal checks */
void print_usage(char *prg)
{
@@ -99,13 +99,13 @@ int main(int argc, char **argv)
while ((opt = getopt(argc, argv, "s:d:x:p:P:b:m:w:f:lL:?")) != -1) {
switch (opt) {
case 's':
addr.can_addr.tp.tx_id = strtoul(optarg, (char **)NULL, 16);
addr.can_addr.tp.tx_id = strtoul(optarg, NULL, 16);
if (strlen(optarg) > 7)
addr.can_addr.tp.tx_id |= CAN_EFF_FLAG;
break;
case 'd':
addr.can_addr.tp.rx_id = strtoul(optarg, (char **)NULL, 16);
addr.can_addr.tp.rx_id = strtoul(optarg, NULL, 16);
if (strlen(optarg) > 7)
addr.can_addr.tp.rx_id |= CAN_EFF_FLAG;
break;
@@ -163,20 +163,20 @@ int main(int argc, char **argv)
break;
case 'b':
fcopts.bs = strtoul(optarg, (char **)NULL, 16) & 0xFF;
fcopts.bs = strtoul(optarg, NULL, 16) & 0xFF;
break;
case 'm':
fcopts.stmin = strtoul(optarg, (char **)NULL, 16) & 0xFF;
fcopts.stmin = strtoul(optarg, NULL, 16) & 0xFF;
break;
case 'w':
fcopts.wftmax = strtoul(optarg, (char **)NULL, 16) & 0xFF;
fcopts.wftmax = strtoul(optarg, NULL, 16) & 0xFF;
break;
case 'f':
opts.flags |= CAN_ISOTP_FORCE_RXSTMIN;
force_rx_stmin = strtoul(optarg, (char **)NULL, 10);
force_rx_stmin = strtoul(optarg, NULL, 10);
break;
case 'l':
@@ -234,6 +234,10 @@ int main(int argc, char **argv)
addr.can_family = AF_CAN;
addr.can_ifindex = if_nametoindex(argv[optind]);
if (!addr.can_ifindex) {
perror("if_nametoindex");
exit(1);
}
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind");
+63 -12
View File
@@ -57,7 +57,8 @@
#include <linux/can/isotp.h>
#define NO_CAN_ID 0xFFFFFFFFU
#define BUFSIZE 5000 /* size > 4095 to check socket API internal checks */
#define BUFSIZE 67000 /* size > 66000 kernel buf to test socket API internal checks */
#define ZERO_STRING "ZERO"
void print_usage(char *prg)
{
@@ -68,14 +69,18 @@ void print_usage(char *prg)
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, " -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 <num> (send num PDUs - use 'i' for infinite loop)\n");
fprintf(stderr, " -g <usecs> (wait given usecs before sending a PDU)\n");
fprintf(stderr, " -b (block until the PDU transmission is completed)\n");
fprintf(stderr, " -S (SF broadcast mode for functional addressing)\n");
fprintf(stderr, " -S (SF broadcast mode - for functional addressing)\n");
fprintf(stderr, " -C (CF broadcast mode - no wait for flow controls)\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, "(*) = Use '-t %s' to set N_As to zero for Linux version 5.18+\n", ZERO_STRING);
fprintf(stderr, "\n");
}
@@ -87,6 +92,8 @@ int main(int argc, char **argv)
static struct can_isotp_ll_options llopts;
int opt;
extern int optind, opterr, optopt;
unsigned int loops = 1; /* one (== no) loop by default */
useconds_t usecs = 0; /* wait before sending the PDU */
__u32 force_tx_stmin = 0;
unsigned char buf[BUFSIZE];
int buflen = 0;
@@ -95,16 +102,16 @@ 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:bSL:?")) != -1) {
while ((opt = getopt(argc, argv, "s:d:x:p:P:t:f:D:l:g:bSCL:?")) != -1) {
switch (opt) {
case 's':
addr.can_addr.tp.tx_id = strtoul(optarg, (char **)NULL, 16);
addr.can_addr.tp.tx_id = strtoul(optarg, NULL, 16);
if (strlen(optarg) > 7)
addr.can_addr.tp.tx_id |= CAN_EFF_FLAG;
break;
case 'd':
addr.can_addr.tp.rx_id = strtoul(optarg, (char **)NULL, 16);
addr.can_addr.tp.rx_id = strtoul(optarg, NULL, 16);
if (strlen(optarg) > 7)
addr.can_addr.tp.rx_id |= CAN_EFF_FLAG;
break;
@@ -162,22 +169,41 @@ int main(int argc, char **argv)
break;
case 't':
opts.frame_txtime = strtoul(optarg, (char **)NULL, 10);
if (!strncmp(optarg, ZERO_STRING, strlen(ZERO_STRING)))
opts.frame_txtime = CAN_ISOTP_FRAME_TXTIME_ZERO;
else
opts.frame_txtime = strtoul(optarg, NULL, 10);
break;
case 'f':
opts.flags |= CAN_ISOTP_FORCE_TXSTMIN;
force_tx_stmin = strtoul(optarg, (char **)NULL, 10);
force_tx_stmin = strtoul(optarg, NULL, 10);
break;
case 'D':
datalen = strtoul(optarg, (char **)NULL, 10);
datalen = strtoul(optarg, NULL, 10);
if (!datalen || datalen >= BUFSIZE) {
print_usage(basename(argv[0]));
exit(0);
}
break;
case 'l':
if (optarg[0] == 'i') {
loops = 0; /* infinite loop */
} else {
loops = strtoul(optarg, NULL, 10);
if (!loops) {
fprintf(stderr, "Invalid argument for option -l!\n");
return 1;
}
}
break;
case 'g':
usecs = strtoul(optarg, NULL, 10);
break;
case 'b':
opts.flags |= CAN_ISOTP_WAIT_TX_DONE;
break;
@@ -186,6 +212,10 @@ int main(int argc, char **argv)
opts.flags |= CAN_ISOTP_SF_BROADCAST;
break;
case 'C':
opts.flags |= CAN_ISOTP_CF_BROADCAST;
break;
case 'L':
if (sscanf(optarg, "%hhu:%hhu:%hhu",
&llopts.mtu,
@@ -210,20 +240,27 @@ int main(int argc, char **argv)
}
}
#define BC_FLAGS (CAN_ISOTP_SF_BROADCAST | CAN_ISOTP_CF_BROADCAST)
if ((argc - optind != 1) ||
(addr.can_addr.tp.tx_id == NO_CAN_ID) ||
((opts.flags & BC_FLAGS) == BC_FLAGS) ||
((addr.can_addr.tp.rx_id == NO_CAN_ID) &&
(!(opts.flags & CAN_ISOTP_SF_BROADCAST)))) {
(!(opts.flags & BC_FLAGS)))) {
print_usage(basename(argv[0]));
exit(1);
}
if ((s = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP)) < 0) {
perror("socket");
exit(1);
}
setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts));
if (setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts)) < 0) {
perror("sockopt");
exit(1);
}
if (llopts.tx_dl) {
if (setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_LL_OPTS, &llopts, sizeof(llopts)) < 0) {
@@ -237,6 +274,10 @@ int main(int argc, char **argv)
addr.can_family = AF_CAN;
addr.can_ifindex = if_nametoindex(argv[optind]);
if (!addr.can_ifindex) {
perror("if_nametoindex");
exit(1);
}
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind");
@@ -252,6 +293,9 @@ int main(int argc, char **argv)
buf[buflen] = ((buflen % 0xFF) + 1) & 0xFF;
}
loop:
if (usecs)
usleep(usecs);
retval = write(s, buf, buflen);
if (retval < 0) {
@@ -262,6 +306,13 @@ int main(int argc, char **argv)
if (retval != buflen)
fprintf(stderr, "wrote only %d from %d byte\n", retval, buflen);
if (loops) {
if (--loops)
goto loop;
} else {
goto loop;
}
/*
* due to a Kernel internal wait queue the PDU is sent completely
* before close() returns.
+11 -7
View File
@@ -166,17 +166,17 @@ int main(int argc, char **argv)
while ((opt = getopt(argc, argv, "l:s:d:x:p:P:b:m:w:t:L:v?")) != -1) {
switch (opt) {
case 'l':
local_port = strtoul(optarg, (char **)NULL, 10);
local_port = strtoul(optarg, NULL, 10);
break;
case 's':
caddr.can_addr.tp.tx_id = strtoul(optarg, (char **)NULL, 16);
caddr.can_addr.tp.tx_id = strtoul(optarg, NULL, 16);
if (strlen(optarg) > 7)
caddr.can_addr.tp.tx_id |= CAN_EFF_FLAG;
break;
case 'd':
caddr.can_addr.tp.rx_id = strtoul(optarg, (char **)NULL, 16);
caddr.can_addr.tp.rx_id = strtoul(optarg, NULL, 16);
if (strlen(optarg) > 7)
caddr.can_addr.tp.rx_id |= CAN_EFF_FLAG;
break;
@@ -234,19 +234,19 @@ int main(int argc, char **argv)
break;
case 'b':
fcopts.bs = strtoul(optarg, (char **)NULL, 16) & 0xFF;
fcopts.bs = strtoul(optarg, NULL, 16) & 0xFF;
break;
case 'm':
fcopts.stmin = strtoul(optarg, (char **)NULL, 16) & 0xFF;
fcopts.stmin = strtoul(optarg, NULL, 16) & 0xFF;
break;
case 'w':
fcopts.wftmax = strtoul(optarg, (char **)NULL, 16) & 0xFF;
fcopts.wftmax = strtoul(optarg, NULL, 16) & 0xFF;
break;
case 't':
opts.frame_txtime = strtoul(optarg, (char **)NULL, 10);
opts.frame_txtime = strtoul(optarg, NULL, 10);
break;
case 'L':
@@ -350,6 +350,10 @@ int main(int argc, char **argv)
caddr.can_family = AF_CAN;
caddr.can_ifindex = if_nametoindex(argv[optind]);
if (!caddr.can_ifindex) {
perror("if_nametoindex");
exit(1);
}
if (bind(sc, (struct sockaddr *)&caddr, caddrlen) < 0) {
perror("bind");
+9 -4
View File
@@ -200,25 +200,25 @@ int main(int argc, char **argv)
while ((opt = getopt(argc, argv, "s:d:x:X:h:ct:f:L:?")) != -1) {
switch (opt) {
case 's':
src = strtoul(optarg, (char **)NULL, 16);
src = strtoul(optarg, NULL, 16);
if (strlen(optarg) > 7)
src |= CAN_EFF_FLAG;
break;
case 'd':
dst = strtoul(optarg, (char **)NULL, 16);
dst = strtoul(optarg, NULL, 16);
if (strlen(optarg) > 7)
dst |= CAN_EFF_FLAG;
break;
case 'x':
opts.flags |= CAN_ISOTP_EXTEND_ADDR;
opts.ext_address = strtoul(optarg, (char **)NULL, 16) & 0xFF;
opts.ext_address = strtoul(optarg, NULL, 16) & 0xFF;
break;
case 'X':
opts.flags |= CAN_ISOTP_RX_EXT_ADDR;
opts.rx_ext_address = strtoul(optarg, (char **)NULL, 16) & 0xFF;
opts.rx_ext_address = strtoul(optarg, NULL, 16) & 0xFF;
break;
case 'f':
@@ -296,6 +296,11 @@ int main(int argc, char **argv)
addr.can_family = AF_CAN;
addr.can_ifindex = if_nametoindex(if_name);
if (!addr.can_ifindex) {
perror("if_nametoindex");
r = 1;
goto out;
}
setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts));
+6 -6
View File
@@ -154,13 +154,13 @@ int main(int argc, char **argv)
while ((opt = getopt(argc, argv, "s:d:n:x:p:P:t:b:m:whL:vD?")) != -1) {
switch (opt) {
case 's':
addr.can_addr.tp.tx_id = strtoul(optarg, (char **)NULL, 16);
addr.can_addr.tp.tx_id = strtoul(optarg, NULL, 16);
if (strlen(optarg) > 7)
addr.can_addr.tp.tx_id |= CAN_EFF_FLAG;
break;
case 'd':
addr.can_addr.tp.rx_id = strtoul(optarg, (char **)NULL, 16);
addr.can_addr.tp.rx_id = strtoul(optarg, NULL, 16);
if (strlen(optarg) > 7)
addr.can_addr.tp.rx_id |= CAN_EFF_FLAG;
break;
@@ -228,19 +228,19 @@ int main(int argc, char **argv)
break;
case 't':
opts.frame_txtime = strtoul(optarg, (char **)NULL, 10);
opts.frame_txtime = strtoul(optarg, NULL, 10);
break;
case 'b':
fcopts.bs = strtoul(optarg, (char **)NULL, 16) & 0xFF;
fcopts.bs = strtoul(optarg, NULL, 16) & 0xFF;
break;
case 'm':
fcopts.stmin = strtoul(optarg, (char **)NULL, 16) & 0xFF;
fcopts.stmin = strtoul(optarg, NULL, 16) & 0xFF;
break;
case 'w':
fcopts.wftmax = strtoul(optarg, (char **)NULL, 16) & 0xFF;
fcopts.wftmax = strtoul(optarg, NULL, 16) & 0xFF;
break;
case 'h':
+114 -23
View File
@@ -42,6 +42,12 @@ struct j1939cat_stats {
int err;
uint32_t tskey;
uint32_t send;
uint32_t total;
uint32_t pgn;
uint8_t sa;
uint8_t da;
uint64_t src_name;
uint64_t dst_name;
};
struct j1939cat_priv {
@@ -67,6 +73,7 @@ struct j1939cat_priv {
struct sock_extended_err *serr;
struct scm_timestamping *tss;
struct j1939cat_stats stats;
int32_t last_dpo;
};
static const char help_msg[] =
@@ -141,7 +148,7 @@ static void j1939cat_print_timestamp(struct j1939cat_priv *priv, const char *nam
if (!(cur->tv_sec | cur->tv_nsec))
return;
fprintf(stderr, " %s: %lu s %lu us (seq=%u, send=%u)",
fprintf(stderr, " %s: %lu s %lu us (seq=%03u, send=%07u)",
name, cur->tv_sec, cur->tv_nsec / 1000,
stats->tskey, stats->send);
@@ -152,13 +159,13 @@ static const char *j1939cat_tstype_to_str(int tstype)
{
switch (tstype) {
case SCM_TSTAMP_SCHED:
return " ENQ";
return "TX ENQ";
case SCM_TSTAMP_SND:
return " SND";
return "TX SND";
case SCM_TSTAMP_ACK:
return " ACK";
return "TX ACK";
default:
return " unk";
return " unk";
}
}
@@ -175,6 +182,24 @@ static void j1939cat_scm_opt_stats(struct j1939cat_priv *priv, void *buf, int le
case J1939_NLA_BYTES_ACKED:
stats->send = *(uint32_t *)((char *)nla + NLA_HDRLEN);
break;
case J1939_NLA_TOTAL_SIZE:
stats->total = *(uint32_t *)((char *)nla + NLA_HDRLEN);
break;
case J1939_NLA_PGN:
stats->pgn = *(uint32_t *)((char *)nla + NLA_HDRLEN);
break;
case J1939_NLA_DEST_ADDR:
stats->da = *(uint8_t *)((char *)nla + NLA_HDRLEN);
break;
case J1939_NLA_SRC_ADDR:
stats->sa = *(uint8_t *)((char *)nla + NLA_HDRLEN);
break;
case J1939_NLA_DEST_NAME:
stats->dst_name = *(uint64_t *)((char *)nla + NLA_HDRLEN);
break;
case J1939_NLA_SRC_NAME:
stats->src_name = *(uint64_t *)((char *)nla + NLA_HDRLEN);
break;
default:
warnx("not supported J1939_NLA field\n");
}
@@ -231,14 +256,39 @@ static int j1939cat_extract_serr(struct j1939cat_priv *priv)
* 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);
switch (serr->ee_info) {
case J1939_EE_INFO_TX_ABORT:
j1939cat_print_timestamp(priv, "TX ABT", &tss->ts[0]);
warnx("serr: tx error: %i, %s", serr->ee_errno,
strerror(serr->ee_errno));
return serr->ee_errno;
case J1939_EE_INFO_RX_RTS:
stats->tskey = serr->ee_data;
j1939cat_print_timestamp(priv, "RX RTS", &tss->ts[0]);
fprintf(stderr, " total size: %u, pgn=0x%05x, sa=0x%02x, da=0x%02x src_name=0x%08" PRIx64 ", dst_name=0x%08" PRIx64 ")\n",
stats->total, stats->pgn, stats->sa, stats->da,
stats->src_name, stats->dst_name);
priv->last_dpo = -1;
return 0;
case J1939_EE_INFO_RX_DPO:
stats->tskey = serr->ee_data;
j1939cat_print_timestamp(priv, "RX DPO", &tss->ts[0]);
if (stats->send <= (uint32_t)priv->last_dpo && priv->last_dpo != -1)
warnx("same dpo? current: %i, last: %i",
stats->send, priv->last_dpo);
priv->last_dpo = stats->send;
return 0;
case J1939_EE_INFO_RX_ABORT:
j1939cat_print_timestamp(priv, "RX ABT", &tss->ts[0]);
warnx("serr: rx error: %i, %s", serr->ee_errno,
strerror(serr->ee_errno));
return serr->ee_errno;
default:
warnx("serr: unknown ee_info: %i", serr->ee_info);
return -ENOTSUP;
}
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;
break;
default:
warnx("serr: wrong origin: %u", serr->ee_origin);
}
@@ -269,7 +319,7 @@ static int j1939cat_parse_cm(struct j1939cat_priv *priv, struct cmsghdr *cm)
static int j1939cat_recv_err(struct j1939cat_priv *priv)
{
char control[100];
char control[200];
struct cmsghdr *cm;
int ret;
struct msghdr msg = {
@@ -318,14 +368,16 @@ static int j1939cat_send_loop(struct j1939cat_priv *priv, int out_fd, char *buf,
int ret;
ret = poll(&fds, 1, priv->polltimeout);
if (ret == -EINTR)
continue;
if (ret < 0)
return -errno;
if (ret == -1) {
if (errno == -EINTR)
continue;
else
return -errno;
}
if (!ret)
return -ETIME;
if (!(fds.revents & events)) {
warn("%s: something else is wrong", __func__);
warn("%s: something else is wrong %x %x", __func__, fds.revents, events);
return -EIO;
}
@@ -457,7 +509,7 @@ static int j1939cat_send(struct j1939cat_priv *priv)
{
unsigned int size = 0;
unsigned int i;
int ret;
int ret = 0;
if (priv->todo_filesize)
size = j1939cat_get_file_size(priv->infile);
@@ -499,6 +551,7 @@ static int j1939cat_recv_one(struct j1939cat_priv *priv, uint8_t *buf, size_t bu
static int j1939cat_recv(struct j1939cat_priv *priv)
{
unsigned int events = POLLIN | POLLERR;
int ret = EXIT_SUCCESS;
size_t buf_size;
uint8_t *buf;
@@ -510,10 +563,48 @@ static int j1939cat_recv(struct j1939cat_priv *priv)
return EXIT_FAILURE;;
}
priv->last_dpo = -1;
while (priv->todo_recv) {
ret = j1939cat_recv_one(priv, buf, buf_size);
if (ret)
break;
if (priv->polltimeout) {
struct pollfd fds = {
.fd = priv->sock,
.events = events,
};
int ret;
ret = poll(&fds, 1, priv->polltimeout);
if (ret == -1) {
if (errno == -EINTR)
continue;
else
return -errno;
}
if (!ret)
continue;
if (!(fds.revents & events)) {
warn("%s: something else is wrong %x %x", __func__, fds.revents, events);
return -EIO;
}
if (fds.revents & POLLERR) {
ret = j1939cat_recv_err(priv);
if (ret == -EINTR)
continue;
if (ret)
return ret;
}
if (fds.revents & POLLIN) {
ret = j1939cat_recv_one(priv, buf, buf_size);
if (ret < 0)
break;
}
} else {
ret = j1939cat_recv_one(priv, buf, buf_size);
if (ret)
break;
}
}
free(buf);
@@ -555,7 +646,7 @@ static int j1939cat_sock_prepare(struct j1939cat_priv *priv)
SOF_TIMESTAMPING_TX_ACK |
SOF_TIMESTAMPING_TX_SCHED |
SOF_TIMESTAMPING_OPT_STATS | SOF_TIMESTAMPING_OPT_TSONLY |
SOF_TIMESTAMPING_OPT_ID;
SOF_TIMESTAMPING_OPT_ID | SOF_TIMESTAMPING_RX_SOFTWARE;
if (setsockopt(priv->sock, SOL_SOCKET, SO_TIMESTAMPING,
(char *) &sock_opt, sizeof(sock_opt)))
+30 -8
View File
@@ -159,7 +159,7 @@ int parse_canframe(char *cs, struct canfd_frame *cf) {
int i, idx, dlen, len;
int maxdlen = CAN_MAX_DLEN;
int ret = CAN_MTU;
unsigned char tmp;
canid_t tmp;
len = strlen(cs);
//printf("'%s' len %d\n", cs, len);
@@ -568,9 +568,20 @@ static int snprintf_error_data(char *buf, size_t len, uint8_t err,
for (i = 0; i < arr_len; i++) {
if (err & (1 << i)) {
if (count)
n += snprintf(buf + n, len - n, ",");
n += snprintf(buf + n, len - n, "%s", arr[i]);
int tmp_n = 0;
if (count){
/* Fix for potential buffer overflow https://lgtm.com/rules/1505913226124/ */
tmp_n = snprintf(buf + n, len - n, ",");
if (tmp_n < 0 || (size_t)tmp_n >= len - n){
return n;
}
n += tmp_n;
}
tmp_n = snprintf(buf + n, len - n, "%s", arr[i]);
if (tmp_n < 0 || (size_t)tmp_n >= len - n){
return n;
}
n += tmp_n;
count++;
}
}
@@ -644,9 +655,20 @@ void snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *c
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]);
int tmp_n = 0;
if (classes){
/* Fix for potential buffer overflow https://lgtm.com/rules/1505913226124/ */
tmp_n = snprintf(buf + n, len - n, "%s", sep);
if (tmp_n < 0 || (size_t)tmp_n >= len - n){
return;
}
n += tmp_n;
}
tmp_n = snprintf(buf + n, len - n, "%s", error_classes[i]);
if (tmp_n < 0 || (size_t)tmp_n >= len - n){
return;
}
n += tmp_n;
if (mask == CAN_ERR_LOSTARB)
n += snprintf_error_lostarb(buf + n, len - n,
cf);
@@ -658,7 +680,7 @@ void snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *c
}
}
if (cf->data[6] || cf->data[7]) {
if (cf->can_id & CAN_ERR_CNT || cf->data[6] || cf->data[7]) {
n += snprintf(buf + n, len - n, "%s", sep);
n += snprintf(buf + n, len - n, "error-counter-tx-rx{{%d}{%d}}",
cf->data[6], cf->data[7]);
+8
View File
@@ -47,6 +47,13 @@
#include <stdio.h>
#ifdef DEBUG
#define pr_debug(fmt, args...) printf(fmt, ##args)
#else
__attribute__((format (printf, 1, 2)))
static inline int pr_debug(const char* fmt, ...) {return 0;}
#endif
/* buffer sizes for CAN frame string representations */
#define CL_ID (sizeof("12345678##1"))
@@ -95,6 +102,7 @@ int hexstring2data(char *arg, unsigned char *data, int maxdlen);
*
*/
struct canfd_frame;
int parse_canframe(char *cs, struct canfd_frame *cf);
/*
* Transfers a valid ASCII string describing a CAN frame into struct canfd_frame.
+3
View File
@@ -10,6 +10,9 @@
* as published by the Free Software Foundation
*/
/* needed on some 64 bit platforms to get consistent 64-bit types */
#define __SANE_USERSPACE_TYPES__
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/j1939.h>
+12 -3
View File
@@ -71,11 +71,13 @@ void print_usage(char *prg)
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)
void can_asc(struct canfd_frame *cfd, int devno, int nortrdlc, char *extra_info, FILE *outfile)
{
int i;
char id[10];
char *dir = "Rx";
int dlc;
struct can_frame *cf = (struct can_frame *)cfd; /* for len8_dlc */
fprintf(outfile, "%-2d ", devno); /* channel number left aligned */
@@ -94,13 +96,20 @@ void can_asc(struct canfd_frame *cf, int devno, int nortrdlc, char *extra_info,
fprintf(outfile, "%-15s %s ", id, dir);
if (cf->len == CAN_MAX_DLC &&
cf->len8_dlc > CAN_MAX_DLC &&
cf->len8_dlc <= CAN_MAX_RAW_DLC)
dlc = cf->len8_dlc;
else
dlc = cf->len;
if (cf->can_id & CAN_RTR_FLAG) {
if (nortrdlc)
fprintf(outfile, "r"); /* RTR frame */
else
fprintf(outfile, "r %d", cf->len); /* RTR frame */
fprintf(outfile, "r %X", dlc); /* RTR frame */
} else {
fprintf(outfile, "d %d", cf->len); /* data frame */
fprintf(outfile, "d %X", dlc); /* data frame */
for (i = 0; i < cf->len; i++) {
fprintf(outfile, " %02X", cf->data[i]);
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+706
View File
@@ -0,0 +1,706 @@
000: 024b0760
004: 001c0900
008: 00050200
00c: 00020600
010: 017fce42
014: 00010000
018: 40400040
01c: 3f1a0000
020: 00000000
024: 00000000
028: 00000000
02c: 00000000
030: 00000000
034: 00000000
038: 00000000
03c: 00000003
040: 03000029
044: 00000000
048: 00000024
04c: 00000000
050: 00600080
054: 00000005
058: 00000030
05c: e3600090
060: 00000307
064: 00000108
068: ef000029
06c: 00000300
070: 00000234
074: 00600000
078: 00000000
07c: 00000610
080: 00600000
084: 00000000
088: 00000620
08c: 00600000
090: 00000000
094: 00000630
098: 00600000
09c: 00000000
0a0: 00000640
0a4: 00600000
0a8: 00000000
0ac: 00000650
0b0: 00600000
0b4: 00000000
0b8: 00000660
0bc: 00600000
0c0: 00000000
0c4: 00000670
0c8: 00600000
0cc: 00000000
0d0: 00000680
0d4: 00600000
0d8: 00000000
0dc: 00000690
0e0: 00600000
0e4: 00000000
0e8: 000006a0
0ec: 00600000
0f0: 00000000
0f4: 000006b0
0f8: 00600000
0fc: 00000000
100: 000006c0
104: 00600000
108: 00000000
10c: 000006d0
110: 00600000
114: 00000000
118: 000006e0
11c: 00600000
120: 00000000
124: 000006f0
128: 00600000
12c: 00000000
130: 00000700
134: 00600000
138: 00000000
13c: 00000710
140: 00600000
144: 00000000
148: 00000720
14c: 00600000
150: 00000000
154: 00000730
158: 00600000
15c: 00000000
160: 00000740
164: 00600000
168: 00000000
16c: 00000750
170: 00600000
174: 00000000
178: 00000760
17c: 00600000
180: 00000000
184: 00000770
188: 00600000
18c: 00000000
190: 00000780
194: 00600000
198: 00000000
19c: 00000790
1a0: 00600000
1a4: 00000000
1a8: 000007a0
1ac: 00600000
1b0: 00000000
1b4: 000007b0
1b8: 00600000
1bc: 00000000
1c0: 000007c0
1c4: 00600000
1c8: 00000000
1cc: 000007d0
1d0: 00000082
1d4: 00000000
1d8: 00000000
1dc: 00000000
1e0: 00000000
1e4: 00000000
1e8: 00000000
1ec: 00000000
1f0: 00000000
1f4: 00000000
1f8: 00000000
1fc: 00000000
200: 00000000
204: 00000000
208: 00000000
20c: 00000000
210: 00000000
214: 00000000
218: 00000000
21c: 00000000
220: 00000000
224: 00000000
228: 00000000
22c: 00000000
230: 00000000
234: 00000000
238: 00000000
23c: 00000000
240: 00000000
244: 00000000
248: 00000000
24c: 00000000
250: 00000000
254: 00000000
258: 00000000
25c: 00000000
260: 00000000
264: 00000000
268: 00000000
26c: 00000000
270: 00000000
274: 00000000
278: 00000000
27c: 00000000
280: 00000000
284: 00000000
288: 00000000
28c: 00000000
290: 00000000
294: 00000000
298: 00000000
29c: 00000000
2a0: 00000000
2a4: 00000000
2a8: 00000000
2ac: 00000000
2b0: 00000000
2b4: 00000000
2b8: 00000000
2bc: 00000000
2c0: 00000000
2c4: 00000000
2c8: 00000000
2cc: 00000000
2d0: 00000000
2d4: 00000000
2d8: 00000000
2dc: 00000000
2e0: 00000000
2e4: 00000000
2e8: 00000000
2ec: 00000000
400: 00000002
404: 00000008
408: 005897d8
40c: 00000002
410: 00000208
414: 00daf340
418: 00000002
41c: 00000408
420: 01585768
424: 00000000
428: 00000000
42c: 00000000
430: 00000002
434: 00000008
438: 00000000
43c: 00000000
440: 00000000
444: 00000000
448: 00000000
44c: 00000000
450: 00000000
454: 00000000
458: 00000000
45c: 00000000
460: 00000000
464: 00000000
468: 00000000
46c: 00000000
470: 00000000
474: 00000000
478: 00000002
47c: 00000208
480: 00000001
484: 00000000
488: 00000000
48c: 00000000
490: 00000000
494: 00000000
498: 00000000
49c: 00000000
4a0: 00000000
4a4: 00000000
4a8: 00000000
4ac: 00000000
4b0: 00000000
4b4: 00000000
4b8: 00000000
4bc: 00000000
4c0: 00000002
4c4: 00000408
4c8: 00000002
4cc: 00000000
4d0: 00000000
4d4: 00000000
4d8: 00000000
4dc: 00000000
4e0: 00000000
4e4: 00000000
4e8: 00000000
4ec: 00000000
4f0: 00000000
4f4: 00000000
4f8: 00000000
4fc: 00000000
500: 00000000
504: 00000000
508: 00000000
50c: 00000000
510: 00000000
514: 00000000
518: 00000000
51c: 00000000
520: 00000000
524: 00000000
528: 00000000
52c: 00000000
530: 00000000
534: 00000000
538: 00000000
53c: 00000000
540: 00000000
544: 00000000
548: 00000000
54c: 00000000
550: 00000002
554: 00000008
558: 005897d8
55c: 00000000
560: 00000000
564: 00000000
568: 00000000
56c: 00000000
570: 00000000
574: 00000000
578: 00000000
57c: 00000000
580: 00000000
584: 00000000
588: 00000000
58c: 00000000
590: 00000000
594: 00000000
598: 00000000
59c: 00000002
5a0: 00000008
5a4: 00daf340
5a8: 00000001
5ac: 00000000
5b0: 00000000
5b4: 00000000
5b8: 00000000
5bc: 00000000
5c0: 00000000
5c4: 00000000
5c8: 00000000
5cc: 00000000
5d0: 00000000
5d4: 00000000
5d8: 00000000
5dc: 00000000
5e0: 00000000
5e4: 00000000
5e8: 00000002
5ec: 00000008
5f0: 01585768
5f4: 00000002
5f8: 00000000
5fc: 00000000
600: 00000000
604: 00000000
608: 00000000
60c: 00000000
610: 00000000
614: 00000000
618: 00000000
61c: 00000000
620: 00000000
624: 00000000
628: 00000000
62c: 00000000
630: 00000000
634: 00000000
638: 00000000
63c: 00000000
640: 00000000
644: 00000000
648: 00000000
64c: 00000000
650: 00000000
654: 00000000
658: 00000000
65c: 00000000
660: 00000000
664: 00000000
668: 00000000
66c: 00000000
670: 00000000
674: 00000000
678: 00000000
67c: 00000000
680: 00000000
684: 00000000
688: 00000000
68c: 00000000
690: 00000000
694: 00000000
698: 00000000
69c: 00000000
6a0: 00000000
6a4: 00000000
6a8: 00000000
6ac: 00000000
6b0: 00000000
6b4: 00000000
6b8: 00000000
6bc: 00000000
6c0: 00000000
6c4: 00000000
6c8: 00000000
6cc: 00000000
6d0: 00000000
6d4: 00000000
6d8: 00000000
6dc: 00000000
6e0: 00000000
6e4: 00000000
6e8: 00000000
6ec: 00000000
6f0: 00000000
6f4: 00000000
6f8: 00000000
6fc: 00000000
700: 00000000
704: 00000000
708: 00000000
70c: 00000000
710: 00000000
714: 00000000
718: 00000000
71c: 00000000
720: 00000000
724: 00000000
728: 00000000
72c: 00000000
730: 00000000
734: 00000000
738: 00000000
73c: 00000000
740: 00000000
744: 00000000
748: 00000000
74c: 00000000
750: 00000000
754: 00000000
758: 00000000
75c: 00000000
760: 00000000
764: 00000000
768: 00000000
76c: 00000000
770: 00000000
774: 00000000
778: 00000000
77c: 00000000
780: 00000000
784: 00000000
788: 00000000
78c: 00000000
790: 00000000
794: 00000000
798: 00000000
79c: 00000000
7a0: 00000000
7a4: 00000000
7a8: 00000000
7ac: 00000000
7b0: 00000000
7b4: 00000000
7b8: 00000000
7bc: 00000000
7c0: 00000000
7c4: 00000000
7c8: 00000000
7cc: 00000000
7d0: 00000000
7d4: 00000000
7d8: 00000000
7dc: 00000000
7e0: 00000000
7e4: 00000000
7e8: 00000000
7ec: 00000000
7f0: 00000000
7f4: 00000000
7f8: 00000000
7fc: 00000000
800: 00000000
804: 00000000
808: 00000000
80c: 00000000
810: 00000000
814: 00000000
818: 00000000
81c: 00000000
820: 00000000
824: 00000000
828: 00000000
82c: 00000000
830: 00000000
834: 00000000
838: 00000000
83c: 00000000
840: 00000000
844: 00000000
848: 00000000
84c: 00000000
850: 00000000
854: 00000000
858: 00000000
85c: 00000000
860: 00000000
864: 00000000
868: 00000000
86c: 00000000
870: 00000000
874: 00000000
878: 00000000
87c: 00000000
880: 00000000
884: 00000000
888: 00000000
88c: 00000000
890: 00000000
894: 00000000
898: 00000000
89c: 00000000
8a0: 00000000
8a4: 00000000
8a8: 00000000
8ac: 00000000
8b0: 00000000
8b4: 00000000
8b8: 00000000
8bc: 00000000
8c0: 00000000
8c4: 00000000
8c8: 00000000
8cc: 00000000
8d0: 00000000
8d4: 00000000
8d8: 00000000
8dc: 00000000
8e0: 00000000
8e4: 00000000
8e8: 00000000
8ec: 00000000
8f0: 00000000
8f4: 00000000
8f8: 00000000
8fc: 00000000
900: 00000000
904: 00000000
908: 00000000
90c: 00000000
910: 00000000
914: 00000000
918: 00000000
91c: 00000000
920: 00000000
924: 00000000
928: 00000000
92c: 00000000
930: 00000000
934: 00000000
938: 00000000
93c: 00000000
940: 00000000
944: 00000000
948: 00000000
94c: 00000000
950: 00000000
954: 00000000
958: 00000000
95c: 00000000
960: 00000000
964: 00000000
968: 00000000
96c: 00000000
970: 00000000
974: 00000000
978: 00000000
97c: 00000000
980: 00000000
984: 00000000
988: 00000000
98c: 00000000
990: 00000000
994: 00000000
998: 00000000
99c: 00000000
9a0: 00000000
9a4: 00000000
9a8: 00000000
9ac: 00000000
9b0: 00000000
9b4: 00000000
9b8: 00000000
9bc: 00000000
9c0: 00000000
9c4: 00000000
9c8: 00000000
9cc: 00000000
9d0: 00000000
9d4: 00000000
9d8: 00000000
9dc: 00000000
9e0: 00000000
9e4: 00000000
9e8: 00000000
9ec: 00000000
9f0: 00000000
9f4: 00000000
9f8: 00000000
9fc: 00000000
a00: 00000000
a04: 00000000
a08: 00000000
a0c: 00000000
a10: 00000000
a14: 00000000
a18: 00000000
a1c: 00000000
a20: 00000000
a24: 00000000
a28: 00000000
a2c: 00000000
a30: 00000000
a34: 00000000
a38: 00000000
a3c: 00000000
a40: 00000000
a44: 00000000
a48: 00000000
a4c: 00000000
a50: 00000000
a54: 00000000
a58: 00000000
a5c: 00000000
a60: 00000000
a64: 00000000
a68: 00000000
a6c: 00000000
a70: 00000000
a74: 00000000
a78: 00000000
a7c: 00000000
a80: 00000000
a84: 00000000
a88: 00000000
a8c: 00000000
a90: 00000000
a94: 00000000
a98: 00000000
a9c: 00000000
aa0: 00000000
aa4: 00000000
aa8: 00000000
aac: 00000000
ab0: 00000000
ab4: 00000000
ab8: 00000000
abc: 00000000
ac0: 00000000
ac4: 00000000
ac8: 00000000
acc: 00000000
ad0: 00000000
ad4: 00000000
ad8: 00000000
adc: 00000000
ae0: 00000000
ae4: 00000000
ae8: 00000000
aec: 00000000
af0: 00000000
af4: 00000000
af8: 00000000
afc: 00000000
b00: 00000000
b04: 00000000
b08: 00000000
b0c: 00000000
b10: 00000000
b14: 00000000
b18: 00000000
b1c: 00000000
b20: 00000000
b24: 00000000
b28: 00000000
b2c: 00000000
b30: 00000000
b34: 00000000
b38: 00000000
b3c: 00000000
b40: 00000000
b44: 00000000
b48: 00000000
b4c: 00000000
b50: 00000000
b54: 00000000
b58: 00000000
b5c: 00000000
b60: 00000000
b64: 00000000
b68: 00000000
b6c: 00000000
b70: 00000000
b74: 00000000
b78: 00000000
b7c: 00000000
b80: 00000000
b84: 00000000
b88: 00000000
b8c: 00000000
b90: 00000000
b94: 00000000
b98: 00000000
b9c: 00000000
ba0: 00000000
ba4: 00000000
ba8: 00000000
bac: 00000000
bb0: 00000000
bb4: 00000000
bb8: 00000000
bbc: 00000000
bc0: 00000000
bc4: 00000000
bc8: 00000000
bcc: 00000000
bd0: 00000000
bd4: 00000000
bd8: 00000000
bdc: 00000000
be0: 00000000
be4: 00000000
be8: 00000000
bec: 00000000
bf0: 00000000
bf4: 00000000
bf8: 00000000
bfc: 00000000
e00: 00000468
e04: 03030003
e08: 03000305
e0c: 00000007
e10: 00000000
e14: 00000000
+706
View File
@@ -0,0 +1,706 @@
000: 05ab0760
004: 001c0900
008: 00050200
00c: 00020600
010: 012937f8
014: 00010000
018: 40400040
01c: 3f1a0000
020: 00000000
024: 00000000
028: 00000000
02c: 00000000
030: 00000000
034: 00000000
038: 00000000
03c: 00000003
040: 03000029
044: 00000000
048: 00000024
04c: 00000000
050: 00600080
054: 00000005
058: 00000030
05c: ef000029
060: 00000300
064: 00000114
068: e3000029
06c: 00000000
070: 000004f0
074: e3600090
078: 00000307
07c: 000006f8
080: 00600000
084: 00000000
088: 00000740
08c: 00600000
090: 00000000
094: 00000750
098: 00600000
09c: 00000000
0a0: 00000760
0a4: 00600000
0a8: 00000000
0ac: 00000770
0b0: 00600000
0b4: 00000000
0b8: 00000780
0bc: 00600000
0c0: 00000000
0c4: 00000790
0c8: 00600000
0cc: 00000000
0d0: 000007a0
0d4: 00600000
0d8: 00000000
0dc: 000007b0
0e0: 00600000
0e4: 00000000
0e8: 000007c0
0ec: 00600000
0f0: 00000000
0f4: 000007d0
0f8: 00600000
0fc: 00000000
100: 000007e0
104: 00600000
108: 00000000
10c: 000007f0
110: 00600000
114: 00000000
118: 00000800
11c: 00600000
120: 00000000
124: 00000810
128: 00600000
12c: 00000000
130: 00000820
134: 00600000
138: 00000000
13c: 00000830
140: 00600000
144: 00000000
148: 00000840
14c: 00600000
150: 00000000
154: 00000850
158: 00600000
15c: 00000000
160: 00000860
164: 00600000
168: 00000000
16c: 00000870
170: 00600000
174: 00000000
178: 00000880
17c: 00600000
180: 00000000
184: 00000890
188: 00600000
18c: 00000000
190: 000008a0
194: 00600000
198: 00000000
19c: 000008b0
1a0: 00600000
1a4: 00000000
1a8: 000008c0
1ac: 00600000
1b0: 00000000
1b4: 000008d0
1b8: 00600000
1bc: 00000000
1c0: 000008e0
1c4: 00600000
1c8: 00000000
1cc: 000008f0
1d0: 00008281
1d4: 00000000
1d8: 00000000
1dc: 00000000
1e0: 00000000
1e4: 00000000
1e8: 00000000
1ec: 00000000
1f0: 00000000
1f4: 00000000
1f8: 00000000
1fc: 00000000
200: 00000000
204: 00000000
208: 00000000
20c: 00000000
210: 00000000
214: 00000000
218: 00000000
21c: 00000000
220: 00000000
224: 00000000
228: 00000000
22c: 00000000
230: 00000000
234: 00000000
238: 00000000
23c: 00000000
240: 00000000
244: 00000000
248: 00000000
24c: 00000000
250: 00000000
254: 00000000
258: 00000000
25c: 00000000
260: 00000000
264: 00000000
268: 00000000
26c: 00000000
270: 00000000
274: 00000000
278: 00000000
27c: 00000000
280: 00000000
284: 00000000
288: 00000000
28c: 00000000
290: 00000000
294: 00000000
298: 00000000
29c: 00000000
2a0: 00000000
2a4: 00000000
2a8: 00000000
2ac: 00000000
2b0: 00000000
2b4: 00000000
2b8: 00000000
2bc: 00000000
2c0: 00000000
2c4: 00000000
2c8: 00000000
2cc: 00000000
2d0: 00000000
2d4: 00000000
2d8: 00000000
2dc: 00000000
2e0: 00000000
2e4: 00000000
2e8: 00000000
2ec: 00000000
400: 00000002
404: 00000008
408: 002badca
40c: 00000002
410: 00000208
414: 00a5e13a
418: 00000002
41c: 00000408
420: 01202382
424: 00000000
428: 00000000
42c: 00000000
430: 00000002
434: 00000008
438: 002badca
43c: 00000000
440: 00000000
444: 00000000
448: 00000000
44c: 00000000
450: 00000000
454: 00000000
458: 00000000
45c: 00000000
460: 00000000
464: 00000000
468: 00000000
46c: 00000000
470: 00000000
474: 00000000
478: 00000000
47c: 00000002
480: 00000008
484: 00a5e13a
488: 00000001
48c: 00000000
490: 00000000
494: 00000000
498: 00000000
49c: 00000000
4a0: 00000000
4a4: 00000000
4a8: 00000000
4ac: 00000000
4b0: 00000000
4b4: 00000000
4b8: 00000000
4bc: 00000000
4c0: 00000000
4c4: 00000000
4c8: 00000002
4cc: 00000008
4d0: 01202382
4d4: 00000002
4d8: 00000000
4dc: 00000000
4e0: 00000000
4e4: 00000000
4e8: 00000000
4ec: 00000000
4f0: 00000000
4f4: 00000000
4f8: 00000000
4fc: 00000000
500: 00000000
504: 00000000
508: 00000000
50c: 00000000
510: 00000000
514: 00000000
518: 00000000
51c: 00000000
520: 00000000
524: 00000000
528: 00000000
52c: 00000000
530: 00000000
534: 00000000
538: 00000000
53c: 00000000
540: 00000000
544: 00000000
548: 00000000
54c: 00000000
550: 00000000
554: 00000000
558: 00000000
55c: 00000000
560: 00000000
564: 00000000
568: 00000000
56c: 00000000
570: 00000000
574: 00000000
578: 00000000
57c: 00000000
580: 00000000
584: 00000000
588: 00000000
58c: 00000000
590: 00000000
594: 00000000
598: 00000000
59c: 00000000
5a0: 00000000
5a4: 00000000
5a8: 00000000
5ac: 00000000
5b0: 00000000
5b4: 00000000
5b8: 00000000
5bc: 00000000
5c0: 00000000
5c4: 00000000
5c8: 00000000
5cc: 00000000
5d0: 00000000
5d4: 00000000
5d8: 00000000
5dc: 00000000
5e0: 00000000
5e4: 00000000
5e8: 00000000
5ec: 00000000
5f0: 00000000
5f4: 00000000
5f8: 00000000
5fc: 00000000
600: 00000000
604: 00000000
608: 00000000
60c: 00000000
610: 00000000
614: 00000000
618: 00000000
61c: 00000000
620: 00000000
624: 00000000
628: 00000000
62c: 00000000
630: 00000000
634: 00000000
638: 00000000
63c: 00000000
640: 00000000
644: 00000000
648: 00000000
64c: 00000000
650: 00000000
654: 00000000
658: 00000000
65c: 00000000
660: 00000000
664: 00000000
668: 00000000
66c: 00000000
670: 00000000
674: 00000000
678: 00000000
67c: 00000000
680: 00000000
684: 00000000
688: 00000000
68c: 00000000
690: 00000000
694: 00000000
698: 00000000
69c: 00000000
6a0: 00000000
6a4: 00000000
6a8: 00000000
6ac: 00000000
6b0: 00000000
6b4: 00000000
6b8: 00000000
6bc: 00000000
6c0: 00000000
6c4: 00000000
6c8: 00000000
6cc: 00000000
6d0: 00000000
6d4: 00000000
6d8: 00000000
6dc: 00000000
6e0: 00000000
6e4: 00000000
6e8: 00000000
6ec: 00000000
6f0: 00000000
6f4: 00000000
6f8: 00000000
6fc: 00000000
700: 00000000
704: 00000000
708: 00000000
70c: 00000000
710: 00000000
714: 00000000
718: 00000000
71c: 00000000
720: 00000000
724: 00000000
728: 00000000
72c: 00000000
730: 00000000
734: 00000000
738: 00000000
73c: 00000000
740: 00000000
744: 00000000
748: 00000000
74c: 00000000
750: 00000000
754: 00000000
758: 00000000
75c: 00000000
760: 00000000
764: 00000000
768: 00000000
76c: 00000000
770: 00000000
774: 00000000
778: 00000000
77c: 00000000
780: 00000000
784: 00000000
788: 00000000
78c: 00000000
790: 00000000
794: 00000000
798: 00000000
79c: 00000000
7a0: 00000000
7a4: 00000000
7a8: 00000000
7ac: 00000000
7b0: 00000000
7b4: 00000000
7b8: 00000000
7bc: 00000000
7c0: 00000000
7c4: 00000000
7c8: 00000000
7cc: 00000000
7d0: 00000000
7d4: 00000000
7d8: 00000000
7dc: 00000000
7e0: 00000000
7e4: 00000000
7e8: 00000000
7ec: 00000000
7f0: 00000000
7f4: 00000000
7f8: 00000000
7fc: 00000000
800: 00000000
804: 00000000
808: 00000000
80c: 00000000
810: 00000000
814: 00000000
818: 00000000
81c: 00000000
820: 00000000
824: 00000000
828: 00000000
82c: 00000000
830: 00000000
834: 00000000
838: 00000000
83c: 00000000
840: 00000000
844: 00000000
848: 00000000
84c: 00000000
850: 00000000
854: 00000000
858: 00000000
85c: 00000000
860: 00000000
864: 00000000
868: 00000000
86c: 00000000
870: 00000000
874: 00000000
878: 00000000
87c: 00000000
880: 00000000
884: 00000000
888: 00000000
88c: 00000000
890: 00000000
894: 00000000
898: 00000000
89c: 00000000
8a0: 00000000
8a4: 00000000
8a8: 00000000
8ac: 00000000
8b0: 00000000
8b4: 00000000
8b8: 00000000
8bc: 00000000
8c0: 00000000
8c4: 00000000
8c8: 00000000
8cc: 00000000
8d0: 00000000
8d4: 00000000
8d8: 00000000
8dc: 00000000
8e0: 00000000
8e4: 00000000
8e8: 00000000
8ec: 00000000
8f0: 00000000
8f4: 00000000
8f8: 00000000
8fc: 00000000
900: 00000000
904: 00000000
908: 00000000
90c: 00000000
910: 00000000
914: 00000000
918: 00000000
91c: 00000000
920: 00000000
924: 00000000
928: 00000000
92c: 00000000
930: 00000000
934: 00000000
938: 00000000
93c: 00000000
940: 00000000
944: 00000000
948: 00000000
94c: 00000000
950: 00000000
954: 00000000
958: 00000000
95c: 00000000
960: 00000000
964: 00000000
968: 00000000
96c: 00000000
970: 00000000
974: 00000000
978: 00000000
97c: 00000000
980: 00000000
984: 00000000
988: 00000000
98c: 00000000
990: 00000000
994: 00000000
998: 00000000
99c: 00000000
9a0: 00000000
9a4: 00000000
9a8: 00000000
9ac: 00000000
9b0: 00000000
9b4: 00000000
9b8: 00000000
9bc: 00000000
9c0: 00000000
9c4: 00000000
9c8: 00000000
9cc: 00000000
9d0: 00000000
9d4: 00000000
9d8: 00000000
9dc: 00000000
9e0: 00000000
9e4: 00000000
9e8: 00000000
9ec: 00000000
9f0: 00000000
9f4: 00000000
9f8: 00000000
9fc: 00000000
a00: 00000000
a04: 00000000
a08: 00000000
a0c: 00000000
a10: 00000000
a14: 00000000
a18: 00000000
a1c: 00000000
a20: 00000002
a24: 00000008
a28: 00000000
a2c: 00000000
a30: 00000000
a34: 00000000
a38: 00000000
a3c: 00000000
a40: 00000000
a44: 00000000
a48: 00000000
a4c: 00000000
a50: 00000000
a54: 00000000
a58: 00000000
a5c: 00000000
a60: 00000000
a64: 00000000
a68: 00000002
a6c: 00000208
a70: 00000001
a74: 00000000
a78: 00000000
a7c: 00000000
a80: 00000000
a84: 00000000
a88: 00000000
a8c: 00000000
a90: 00000000
a94: 00000000
a98: 00000000
a9c: 00000000
aa0: 00000000
aa4: 00000000
aa8: 00000000
aac: 00000000
ab0: 00000002
ab4: 00000408
ab8: 00000002
abc: 00000000
ac0: 00000000
ac4: 00000000
ac8: 00000000
acc: 00000000
ad0: 00000000
ad4: 00000000
ad8: 00000000
adc: 00000000
ae0: 00000000
ae4: 00000000
ae8: 00000000
aec: 00000000
af0: 00000000
af4: 00000000
af8: 00000000
afc: 00000000
b00: 00000000
b04: 00000000
b08: 00000000
b0c: 00000000
b10: 00000000
b14: 00000000
b18: 00000000
b1c: 00000000
b20: 00000000
b24: 00000000
b28: 00000000
b2c: 00000000
b30: 00000000
b34: 00000000
b38: 00000000
b3c: 00000000
b40: 00000000
b44: 00000000
b48: 00000000
b4c: 00000000
b50: 00000000
b54: 00000000
b58: 00000000
b5c: 00000000
b60: 00000000
b64: 00000000
b68: 00000000
b6c: 00000000
b70: 00000000
b74: 00000000
b78: 00000000
b7c: 00000000
b80: 00000000
b84: 00000000
b88: 00000000
b8c: 00000000
b90: 00000000
b94: 00000000
b98: 00000000
b9c: 00000000
ba0: 00000000
ba4: 00000000
ba8: 00000000
bac: 00000000
bb0: 00000000
bb4: 00000000
bb8: 00000000
bbc: 00000000
bc0: 00000000
bc4: 00000000
bc8: 00000000
bcc: 00000000
bd0: 00000000
bd4: 00000000
bd8: 00000000
bdc: 00000000
be0: 00000000
be4: 00000000
be8: 00000000
bec: 00000000
bf0: 00000000
bf4: 00000000
bf8: 00000000
bfc: 00000000
e00: 00000468
e04: 03030003
e08: 03000305
e0c: 00000007
e10: 00000000
e14: 00000000
@@ -0,0 +1,706 @@
000: 024b0760
004: 001c0900
008: 000e0303
00c: 00021000
010: 0380d6b3
014: 00010000
018: 40400040
01c: 3f1a0000
020: 00000000
024: 00000000
028: 00000000
02c: 00000000
030: 00000000
034: 00000000
038: 00000000
03c: 00000007
040: 07000029
044: 00000000
048: 00000054
04c: 00000000
050: 00600080
054: 00000005
058: 00000060
05c: 07600090
060: 00000707
064: 000000d0
068: 1f000029
06c: 00000700
070: 0000016c
074: 00600000
078: 00000000
07c: 00000360
080: 00600000
084: 00000000
088: 00000370
08c: 00600000
090: 00000000
094: 00000380
098: 00600000
09c: 00000000
0a0: 00000390
0a4: 00600000
0a8: 00000000
0ac: 000003a0
0b0: 00600000
0b4: 00000000
0b8: 000003b0
0bc: 00600000
0c0: 00000000
0c4: 000003c0
0c8: 00600000
0cc: 00000000
0d0: 000003d0
0d4: 00600000
0d8: 00000000
0dc: 000003e0
0e0: 00600000
0e4: 00000000
0e8: 000003f0
0ec: 00600000
0f0: 00000000
0f4: 00000400
0f8: 00600000
0fc: 00000000
100: 00000410
104: 00600000
108: 00000000
10c: 00000420
110: 00600000
114: 00000000
118: 00000430
11c: 00600000
120: 00000000
124: 00000440
128: 00600000
12c: 00000000
130: 00000450
134: 00600000
138: 00000000
13c: 00000460
140: 00600000
144: 00000000
148: 00000470
14c: 00600000
150: 00000000
154: 00000480
158: 00600000
15c: 00000000
160: 00000490
164: 00600000
168: 00000000
16c: 000004a0
170: 00600000
174: 00000000
178: 000004b0
17c: 00600000
180: 00000000
184: 000004c0
188: 00600000
18c: 00000000
190: 000004d0
194: 00600000
198: 00000000
19c: 000004e0
1a0: 00600000
1a4: 00000000
1a8: 000004f0
1ac: 00600000
1b0: 00000000
1b4: 00000500
1b8: 00600000
1bc: 00000000
1c0: 00000510
1c4: 00600000
1c8: 00000000
1cc: 00000520
1d0: 00000082
1d4: 00000000
1d8: 00000000
1dc: 00000000
1e0: 00000000
1e4: 00000000
1e8: 00000000
1ec: 00000000
1f0: 00000000
1f4: 00000000
1f8: 00000000
1fc: 00000000
200: 00000000
204: 00000000
208: 00000000
20c: 00000000
210: 00000000
214: 00000000
218: 00000000
21c: 00000000
220: 00000000
224: 00000000
228: 00000000
22c: 00000000
230: 00000000
234: 00000000
238: 00000000
23c: 00000000
240: 00000000
244: 00000000
248: 00000000
24c: 00000000
250: 00000000
254: 00000000
258: 00000000
25c: 00000000
260: 00000000
264: 00000000
268: 00000000
26c: 00000000
270: 00000000
274: 00000000
278: 00000000
27c: 00000000
280: 00000000
284: 00000000
288: 00000000
28c: 00000000
290: 00000000
294: 00000000
298: 00000000
29c: 00000000
2a0: 00000000
2a4: 00000000
2a8: 00000000
2ac: 00000000
2b0: 00000000
2b4: 00000000
2b8: 00000000
2bc: 00000000
2c0: 00000000
2c4: 00000000
2c8: 00000000
2cc: 00000000
2d0: 00000000
2d4: 00000000
2d8: 00000000
2dc: 00000000
2e0: 00000000
2e4: 00000000
2e8: 00000000
2ec: 00000000
400: 00000002
404: 00000008
408: 00640279
40c: 00000002
410: 00000208
414: 00e52ec1
418: 00000002
41c: 00000408
420: 01627f61
424: 00000002
428: 00000608
42c: 01e002a1
430: 00000002
434: 00000808
438: 025f8459
43c: 00000002
440: 00000a08
444: 02dc5e61
448: 00000002
44c: 00000c08
450: 0359f7d1
454: 00000000
458: 00000000
45c: 00000000
460: 00000002
464: 00000008
468: 00000000
46c: 00000000
470: 00000002
474: 00000208
478: 00000001
47c: 00000000
480: 00000002
484: 00000408
488: 00000002
48c: 00000000
490: 00000002
494: 00000608
498: 00000003
49c: 00000000
4a0: 00000002
4a4: 00000808
4a8: 00000004
4ac: 00000000
4b0: 00000002
4b4: 00000a08
4b8: 00000005
4bc: 00000000
4c0: 00000002
4c4: 00000c08
4c8: 00000006
4cc: 00000000
4d0: 00000000
4d4: 00000000
4d8: 00000000
4dc: 00000000
4e0: 00000002
4e4: 00000008
4e8: 00640279
4ec: 00000000
4f0: 00000000
4f4: 00000002
4f8: 00000008
4fc: 00e52ec1
500: 00000001
504: 00000000
508: 00000002
50c: 00000008
510: 01627f61
514: 00000002
518: 00000000
51c: 00000002
520: 00000008
524: 01e002a1
528: 00000003
52c: 00000000
530: 00000002
534: 00000008
538: 025f8459
53c: 00000004
540: 00000000
544: 00000002
548: 00000008
54c: 02dc5e61
550: 00000005
554: 00000000
558: 00000002
55c: 00000008
560: 0359f7d1
564: 00000006
568: 00000000
56c: 00000000
570: 00000000
574: 00000000
578: 00000000
57c: 00000000
580: 00000000
584: 00000000
588: 00000000
58c: 00000000
590: 00000000
594: 00000000
598: 00000000
59c: 00000000
5a0: 00000000
5a4: 00000000
5a8: 00000000
5ac: 00000000
5b0: 00000000
5b4: 00000000
5b8: 00000000
5bc: 00000000
5c0: 00000000
5c4: 00000000
5c8: 00000000
5cc: 00000000
5d0: 00000000
5d4: 00000000
5d8: 00000000
5dc: 00000000
5e0: 00000000
5e4: 00000000
5e8: 00000000
5ec: 00000000
5f0: 00000000
5f4: 00000000
5f8: 00000000
5fc: 00000000
600: 00000000
604: 00000000
608: 00000000
60c: 00000000
610: 00000000
614: 00000000
618: 00000000
61c: 00000000
620: 00000000
624: 00000000
628: 00000000
62c: 00000000
630: 00000000
634: 00000000
638: 00000000
63c: 00000000
640: 00000000
644: 00000000
648: 00000000
64c: 00000000
650: 00000000
654: 00000000
658: 00000000
65c: 00000000
660: 00000000
664: 00000000
668: 00000000
66c: 00000000
670: 00000000
674: 00000000
678: 00000000
67c: 00000000
680: 00000000
684: 00000000
688: 00000000
68c: 00000000
690: 00000000
694: 00000000
698: 00000000
69c: 00000000
6a0: 00000000
6a4: 00000000
6a8: 00000000
6ac: 00000000
6b0: 00000000
6b4: 00000000
6b8: 00000000
6bc: 00000000
6c0: 00000000
6c4: 00000000
6c8: 00000000
6cc: 00000000
6d0: 00000000
6d4: 00000000
6d8: 00000000
6dc: 00000000
6e0: 00000000
6e4: 00000000
6e8: 00000000
6ec: 00000000
6f0: 00000000
6f4: 00000000
6f8: 00000000
6fc: 00000000
700: 00000000
704: 00000000
708: 00000000
70c: 00000000
710: 00000000
714: 00000000
718: 00000000
71c: 00000000
720: 00000000
724: 00000000
728: 00000000
72c: 00000000
730: 00000000
734: 00000000
738: 00000000
73c: 00000000
740: 00000000
744: 00000000
748: 00000000
74c: 00000000
750: 00000000
754: 00000000
758: 00000000
75c: 00000000
760: 00000000
764: 00000000
768: 00000000
76c: 00000000
770: 00000000
774: 00000000
778: 00000000
77c: 00000000
780: 00000000
784: 00000000
788: 00000000
78c: 00000000
790: 00000000
794: 00000000
798: 00000000
79c: 00000000
7a0: 00000000
7a4: 00000000
7a8: 00000000
7ac: 00000000
7b0: 00000000
7b4: 00000000
7b8: 00000000
7bc: 00000000
7c0: 00000000
7c4: 00000000
7c8: 00000000
7cc: 00000000
7d0: 00000000
7d4: 00000000
7d8: 00000000
7dc: 00000000
7e0: 00000000
7e4: 00000000
7e8: 00000000
7ec: 00000000
7f0: 00000000
7f4: 00000000
7f8: 00000000
7fc: 00000000
800: 00000000
804: 00000000
808: 00000000
80c: 00000000
810: 00000000
814: 00000000
818: 00000000
81c: 00000000
820: 00000000
824: 00000000
828: 00000000
82c: 00000000
830: 00000000
834: 00000000
838: 00000000
83c: 00000000
840: 00000000
844: 00000000
848: 00000000
84c: 00000000
850: 00000000
854: 00000000
858: 00000000
85c: 00000000
860: 00000000
864: 00000000
868: 00000000
86c: 00000000
870: 00000000
874: 00000000
878: 00000000
87c: 00000000
880: 00000000
884: 00000000
888: 00000000
88c: 00000000
890: 00000000
894: 00000000
898: 00000000
89c: 00000000
8a0: 00000000
8a4: 00000000
8a8: 00000000
8ac: 00000000
8b0: 00000000
8b4: 00000000
8b8: 00000000
8bc: 00000000
8c0: 00000000
8c4: 00000000
8c8: 00000000
8cc: 00000000
8d0: 00000000
8d4: 00000000
8d8: 00000000
8dc: 00000000
8e0: 00000000
8e4: 00000000
8e8: 00000000
8ec: 00000000
8f0: 00000000
8f4: 00000000
8f8: 00000000
8fc: 00000000
900: 00000000
904: 00000000
908: 00000000
90c: 00000000
910: 00000000
914: 00000000
918: 00000000
91c: 00000000
920: 00000000
924: 00000000
928: 00000000
92c: 00000000
930: 00000000
934: 00000000
938: 00000000
93c: 00000000
940: 00000000
944: 00000000
948: 00000000
94c: 00000000
950: 00000000
954: 00000000
958: 00000000
95c: 00000000
960: 00000000
964: 00000000
968: 00000000
96c: 00000000
970: 00000000
974: 00000000
978: 00000000
97c: 00000000
980: 00000000
984: 00000000
988: 00000000
98c: 00000000
990: 00000000
994: 00000000
998: 00000000
99c: 00000000
9a0: 00000000
9a4: 00000000
9a8: 00000000
9ac: 00000000
9b0: 00000000
9b4: 00000000
9b8: 00000000
9bc: 00000000
9c0: 00000000
9c4: 00000000
9c8: 00000000
9cc: 00000000
9d0: 00000000
9d4: 00000000
9d8: 00000000
9dc: 00000000
9e0: 00000000
9e4: 00000000
9e8: 00000000
9ec: 00000000
9f0: 00000000
9f4: 00000000
9f8: 00000000
9fc: 00000000
a00: 00000000
a04: 00000000
a08: 00000000
a0c: 00000000
a10: 00000000
a14: 00000000
a18: 00000000
a1c: 00000000
a20: 00000000
a24: 00000000
a28: 00000000
a2c: 00000000
a30: 00000000
a34: 00000000
a38: 00000000
a3c: 00000000
a40: 00000000
a44: 00000000
a48: 00000000
a4c: 00000000
a50: 00000000
a54: 00000000
a58: 00000000
a5c: 00000000
a60: 00000000
a64: 00000000
a68: 00000000
a6c: 00000000
a70: 00000000
a74: 00000000
a78: 00000000
a7c: 00000000
a80: 00000000
a84: 00000000
a88: 00000000
a8c: 00000000
a90: 00000000
a94: 00000000
a98: 00000000
a9c: 00000000
aa0: 00000000
aa4: 00000000
aa8: 00000000
aac: 00000000
ab0: 00000000
ab4: 00000000
ab8: 00000000
abc: 00000000
ac0: 00000000
ac4: 00000000
ac8: 00000000
acc: 00000000
ad0: 00000000
ad4: 00000000
ad8: 00000000
adc: 00000000
ae0: 00000000
ae4: 00000000
ae8: 00000000
aec: 00000000
af0: 00000000
af4: 00000000
af8: 00000000
afc: 00000000
b00: 00000000
b04: 00000000
b08: 00000000
b0c: 00000000
b10: 00000000
b14: 00000000
b18: 00000000
b1c: 00000000
b20: 00000000
b24: 00000000
b28: 00000000
b2c: 00000000
b30: 00000000
b34: 00000000
b38: 00000000
b3c: 00000000
b40: 00000000
b44: 00000000
b48: 00000000
b4c: 00000000
b50: 00000000
b54: 00000000
b58: 00000000
b5c: 00000000
b60: 00000000
b64: 00000000
b68: 00000000
b6c: 00000000
b70: 00000000
b74: 00000000
b78: 00000000
b7c: 00000000
b80: 00000000
b84: 00000000
b88: 00000000
b8c: 00000000
b90: 00000000
b94: 00000000
b98: 00000000
b9c: 00000000
ba0: 00000000
ba4: 00000000
ba8: 00000000
bac: 00000000
bb0: 00000000
bb4: 00000000
bb8: 00000000
bbc: 00000000
bc0: 00000000
bc4: 00000000
bc8: 00000000
bcc: 00000000
bd0: 00000000
bd4: 00000000
bd8: 00000000
bdc: 00000000
be0: 00000000
be4: 00000000
be8: 00000000
bec: 00000000
bf0: 00000000
bf4: 00000000
bf8: 00000000
bfc: 00000000
e00: 00000468
e04: 03030003
e08: 03000305
e0c: 00000007
e10: 00000000
e14: 00000000
+706
View File
@@ -0,0 +1,706 @@
000: 05ab0760
004: 001c0900
008: 000e0303
00c: 00021000
010: 03184e05
014: 00010000
018: 40400040
01c: 3f1a0000
020: 00000000
024: 00000000
028: 00000000
02c: 00000000
030: 00000000
034: 00000000
038: 00000000
03c: 00000007
040: 07000029
044: 00000000
048: 00000054
04c: 00000000
050: 00600080
054: 00000005
058: 00000060
05c: 1f000029
060: 00000700
064: 000000ec
068: 1f000029
06c: 00000000
070: 000002e0
074: 0f000029
078: 00000000
07c: 00000560
080: 07600090
084: 00000707
088: 00000710
08c: 00600000
090: 00000000
094: 00000720
098: 00600000
09c: 00000000
0a0: 00000730
0a4: 00600000
0a8: 00000000
0ac: 00000740
0b0: 00600000
0b4: 00000000
0b8: 00000750
0bc: 00600000
0c0: 00000000
0c4: 00000760
0c8: 00600000
0cc: 00000000
0d0: 00000770
0d4: 00600000
0d8: 00000000
0dc: 00000780
0e0: 00600000
0e4: 00000000
0e8: 00000790
0ec: 00600000
0f0: 00000000
0f4: 000007a0
0f8: 00600000
0fc: 00000000
100: 000007b0
104: 00600000
108: 00000000
10c: 000007c0
110: 00600000
114: 00000000
118: 000007d0
11c: 00600000
120: 00000000
124: 000007e0
128: 00600000
12c: 00000000
130: 000007f0
134: 00600000
138: 00000000
13c: 00000800
140: 00600000
144: 00000000
148: 00000810
14c: 00600000
150: 00000000
154: 00000820
158: 00600000
15c: 00000000
160: 00000830
164: 00600000
168: 00000000
16c: 00000840
170: 00600000
174: 00000000
178: 00000850
17c: 00600000
180: 00000000
184: 00000860
188: 00600000
18c: 00000000
190: 00000870
194: 00600000
198: 00000000
19c: 00000880
1a0: 00600000
1a4: 00000000
1a8: 00000890
1ac: 00600000
1b0: 00000000
1b4: 000008a0
1b8: 00600000
1bc: 00000000
1c0: 000008b0
1c4: 00600000
1c8: 00000000
1cc: 000008c0
1d0: 00838281
1d4: 00000000
1d8: 00000000
1dc: 00000000
1e0: 00000000
1e4: 00000000
1e8: 00000000
1ec: 00000000
1f0: 00000000
1f4: 00000000
1f8: 00000000
1fc: 00000000
200: 00000000
204: 00000000
208: 00000000
20c: 00000000
210: 00000000
214: 00000000
218: 00000000
21c: 00000000
220: 00000000
224: 00000000
228: 00000000
22c: 00000000
230: 00000000
234: 00000000
238: 00000000
23c: 00000000
240: 00000000
244: 00000000
248: 00000000
24c: 00000000
250: 00000000
254: 00000000
258: 00000000
25c: 00000000
260: 00000000
264: 00000000
268: 00000000
26c: 00000000
270: 00000000
274: 00000000
278: 00000000
27c: 00000000
280: 00000000
284: 00000000
288: 00000000
28c: 00000000
290: 00000000
294: 00000000
298: 00000000
29c: 00000000
2a0: 00000000
2a4: 00000000
2a8: 00000000
2ac: 00000000
2b0: 00000000
2b4: 00000000
2b8: 00000000
2bc: 00000000
2c0: 00000000
2c4: 00000000
2c8: 00000000
2cc: 00000000
2d0: 00000000
2d4: 00000000
2d8: 00000000
2dc: 00000000
2e0: 00000000
2e4: 00000000
2e8: 00000000
2ec: 00000000
400: 00000002
404: 00000008
408: 002a5227
40c: 00000002
410: 00000208
414: 00a49627
418: 00000002
41c: 00000408
420: 011edd47
424: 00000002
428: 00000608
42c: 0199149f
430: 00000002
434: 00000808
438: 021357d7
43c: 00000002
440: 00000a08
444: 028d9e07
448: 00000002
44c: 00000c08
450: 0307e45f
454: 00000000
458: 00000000
45c: 00000000
460: 00000002
464: 00000008
468: 002a5227
46c: 00000000
470: 00000000
474: 00000002
478: 00000008
47c: 00a49627
480: 00000001
484: 00000000
488: 00000002
48c: 00000008
490: 011edd47
494: 00000002
498: 00000000
49c: 00000002
4a0: 00000008
4a4: 0199149f
4a8: 00000003
4ac: 00000000
4b0: 00000002
4b4: 00000008
4b8: 021357d7
4bc: 00000004
4c0: 00000000
4c4: 00000002
4c8: 00000008
4cc: 028d9e07
4d0: 00000005
4d4: 00000000
4d8: 00000002
4dc: 00000008
4e0: 0307e45f
4e4: 00000006
4e8: 00000000
4ec: 00000000
4f0: 00000000
4f4: 00000000
4f8: 00000000
4fc: 00000000
500: 00000000
504: 00000000
508: 00000000
50c: 00000000
510: 00000000
514: 00000000
518: 00000000
51c: 00000000
520: 00000000
524: 00000000
528: 00000000
52c: 00000000
530: 00000000
534: 00000000
538: 00000000
53c: 00000000
540: 00000000
544: 00000000
548: 00000000
54c: 00000000
550: 00000000
554: 00000000
558: 00000000
55c: 00000000
560: 00000000
564: 00000000
568: 00000000
56c: 00000000
570: 00000000
574: 00000000
578: 00000000
57c: 00000000
580: 00000000
584: 00000000
588: 00000000
58c: 00000000
590: 00000000
594: 00000000
598: 00000000
59c: 00000000
5a0: 00000000
5a4: 00000000
5a8: 00000000
5ac: 00000000
5b0: 00000000
5b4: 00000000
5b8: 00000000
5bc: 00000000
5c0: 00000000
5c4: 00000000
5c8: 00000000
5cc: 00000000
5d0: 00000000
5d4: 00000000
5d8: 00000000
5dc: 00000000
5e0: 00000000
5e4: 00000000
5e8: 00000000
5ec: 00000000
5f0: 00000000
5f4: 00000000
5f8: 00000000
5fc: 00000000
600: 00000000
604: 00000000
608: 00000000
60c: 00000000
610: 00000000
614: 00000000
618: 00000000
61c: 00000000
620: 00000000
624: 00000000
628: 00000000
62c: 00000000
630: 00000000
634: 00000000
638: 00000000
63c: 00000000
640: 00000000
644: 00000000
648: 00000000
64c: 00000000
650: 00000000
654: 00000000
658: 00000000
65c: 00000000
660: 00000000
664: 00000000
668: 00000000
66c: 00000000
670: 00000000
674: 00000000
678: 00000000
67c: 00000000
680: 00000000
684: 00000000
688: 00000000
68c: 00000000
690: 00000000
694: 00000000
698: 00000000
69c: 00000000
6a0: 00000000
6a4: 00000000
6a8: 00000000
6ac: 00000000
6b0: 00000000
6b4: 00000000
6b8: 00000000
6bc: 00000000
6c0: 00000000
6c4: 00000000
6c8: 00000000
6cc: 00000000
6d0: 00000000
6d4: 00000000
6d8: 00000000
6dc: 00000000
6e0: 00000000
6e4: 00000000
6e8: 00000000
6ec: 00000000
6f0: 00000000
6f4: 00000000
6f8: 00000000
6fc: 00000000
700: 00000000
704: 00000000
708: 00000000
70c: 00000000
710: 00000000
714: 00000000
718: 00000000
71c: 00000000
720: 00000000
724: 00000000
728: 00000000
72c: 00000000
730: 00000000
734: 00000000
738: 00000000
73c: 00000000
740: 00000000
744: 00000000
748: 00000000
74c: 00000000
750: 00000000
754: 00000000
758: 00000000
75c: 00000000
760: 00000000
764: 00000000
768: 00000000
76c: 00000000
770: 00000000
774: 00000000
778: 00000000
77c: 00000000
780: 00000000
784: 00000000
788: 00000000
78c: 00000000
790: 00000000
794: 00000000
798: 00000000
79c: 00000000
7a0: 00000000
7a4: 00000000
7a8: 00000000
7ac: 00000000
7b0: 00000000
7b4: 00000000
7b8: 00000000
7bc: 00000000
7c0: 00000000
7c4: 00000000
7c8: 00000000
7cc: 00000000
7d0: 00000000
7d4: 00000000
7d8: 00000000
7dc: 00000000
7e0: 00000000
7e4: 00000000
7e8: 00000000
7ec: 00000000
7f0: 00000000
7f4: 00000000
7f8: 00000000
7fc: 00000000
800: 00000000
804: 00000000
808: 00000000
80c: 00000000
810: 00000000
814: 00000000
818: 00000000
81c: 00000000
820: 00000000
824: 00000000
828: 00000000
82c: 00000000
830: 00000000
834: 00000000
838: 00000000
83c: 00000000
840: 00000000
844: 00000000
848: 00000000
84c: 00000000
850: 00000000
854: 00000000
858: 00000000
85c: 00000000
860: 00000000
864: 00000000
868: 00000000
86c: 00000000
870: 00000000
874: 00000000
878: 00000000
87c: 00000000
880: 00000000
884: 00000000
888: 00000000
88c: 00000000
890: 00000000
894: 00000000
898: 00000000
89c: 00000000
8a0: 00000000
8a4: 00000000
8a8: 00000000
8ac: 00000000
8b0: 00000000
8b4: 00000000
8b8: 00000000
8bc: 00000000
8c0: 00000000
8c4: 00000000
8c8: 00000000
8cc: 00000000
8d0: 00000000
8d4: 00000000
8d8: 00000000
8dc: 00000000
8e0: 00000000
8e4: 00000000
8e8: 00000000
8ec: 00000000
8f0: 00000000
8f4: 00000000
8f8: 00000000
8fc: 00000000
900: 00000000
904: 00000000
908: 00000000
90c: 00000000
910: 00000000
914: 00000000
918: 00000000
91c: 00000000
920: 00000000
924: 00000000
928: 00000000
92c: 00000000
930: 00000000
934: 00000000
938: 00000000
93c: 00000000
940: 00000000
944: 00000000
948: 00000000
94c: 00000000
950: 00000000
954: 00000000
958: 00000000
95c: 00000000
960: 00000000
964: 00000000
968: 00000000
96c: 00000000
970: 00000000
974: 00000000
978: 00000000
97c: 00000000
980: 00000000
984: 00000000
988: 00000000
98c: 00000000
990: 00000000
994: 00000000
998: 00000000
99c: 00000000
9a0: 00000000
9a4: 00000000
9a8: 00000000
9ac: 00000000
9b0: 00000000
9b4: 00000000
9b8: 00000000
9bc: 00000000
9c0: 00000000
9c4: 00000000
9c8: 00000000
9cc: 00000000
9d0: 00000000
9d4: 00000000
9d8: 00000000
9dc: 00000000
9e0: 00000000
9e4: 00000000
9e8: 00000000
9ec: 00000000
9f0: 00000000
9f4: 00000000
9f8: 00000000
9fc: 00000000
a00: 00000000
a04: 00000000
a08: 00000000
a0c: 00000000
a10: 00000000
a14: 00000000
a18: 00000000
a1c: 00000000
a20: 00000000
a24: 00000000
a28: 00000000
a2c: 00000000
a30: 00000000
a34: 00000000
a38: 00000000
a3c: 00000000
a40: 00000000
a44: 00000000
a48: 00000000
a4c: 00000000
a50: 00000000
a54: 00000000
a58: 00000000
a5c: 00000000
a60: 00000000
a64: 00000000
a68: 00000000
a6c: 00000000
a70: 00000000
a74: 00000000
a78: 00000000
a7c: 00000000
a80: 00000000
a84: 00000000
a88: 00000000
a8c: 00000000
a90: 00000000
a94: 00000000
a98: 00000000
a9c: 00000000
aa0: 00000002
aa4: 00000008
aa8: 00000000
aac: 00000000
ab0: 00000002
ab4: 00000208
ab8: 00000001
abc: 00000000
ac0: 00000002
ac4: 00000408
ac8: 00000002
acc: 00000000
ad0: 00000002
ad4: 00000608
ad8: 00000003
adc: 00000000
ae0: 00000002
ae4: 00000808
ae8: 00000004
aec: 00000000
af0: 00000002
af4: 00000a08
af8: 00000005
afc: 00000000
b00: 00000002
b04: 00000c08
b08: 00000006
b0c: 00000000
b10: 00000000
b14: 00000000
b18: 00000000
b1c: 00000000
b20: 00000000
b24: 00000000
b28: 00000000
b2c: 00000000
b30: 00000000
b34: 00000000
b38: 00000000
b3c: 00000000
b40: 00000000
b44: 00000000
b48: 00000000
b4c: 00000000
b50: 00000000
b54: 00000000
b58: 00000000
b5c: 00000000
b60: 00000000
b64: 00000000
b68: 00000000
b6c: 00000000
b70: 00000000
b74: 00000000
b78: 00000000
b7c: 00000000
b80: 00000000
b84: 00000000
b88: 00000000
b8c: 00000000
b90: 00000000
b94: 00000000
b98: 00000000
b9c: 00000000
ba0: 00000000
ba4: 00000000
ba8: 00000000
bac: 00000000
bb0: 00000000
bb4: 00000000
bb8: 00000000
bbc: 00000000
bc0: 00000000
bc4: 00000000
bc8: 00000000
bcc: 00000000
bd0: 00000000
bd4: 00000000
bd8: 00000000
bdc: 00000000
be0: 00000000
be4: 00000000
be8: 00000000
bec: 00000000
bf0: 00000000
bf4: 00000000
bf8: 00000000
bfc: 00000000
e00: 00000468
e04: 03030003
e08: 03000305
e0c: 00000007
e10: 00000000
e14: 00000000
+22 -24
View File
@@ -17,19 +17,10 @@
#include <linux/kernel.h>
#include "lib.h"
#include "mcp251xfd.h"
#include "mcp251xfd-dump-userspace.h"
#define pr_err(fmt, args...) fprintf(stderr, fmt, ##args)
#define pr_no(fmt, args...) while (0) { fprintf(stdout, fmt, ##args); }
#ifdef DEBUG
#define pr_debug(fmt, args...) pr_err(fmt, ##args)
#else
#define pr_debug(fmt, args...) pr_no(fmt, ##args)
#endif
struct mcp251xfd_dump_iter {
const void *start;
const struct mcp251xfd_dump_object_header *hdr;
@@ -37,20 +28,20 @@ struct mcp251xfd_dump_iter {
const void *object_end;
};
static __attribute__((__unused__)) const char *
const char *
get_object_type_str(enum mcp251xfd_dump_object_type object_type)
{
switch (object_type) {
case MCP251XFD_DUMP_OBJECT_TYPE_REG:
return "reg";
return "REG";
case MCP251XFD_DUMP_OBJECT_TYPE_TEF:
return "tef";
return "TEF";
case MCP251XFD_DUMP_OBJECT_TYPE_RX:
return "rx";
return "RX";
case MCP251XFD_DUMP_OBJECT_TYPE_TX:
return "tx";
return "TX";
case MCP251XFD_DUMP_OBJECT_TYPE_END:
return "end";
return "END";
default:
return "<unknown>";
}
@@ -94,7 +85,7 @@ do_dev_coredump_read_reg(const struct mcp251xfd_priv *priv,
reg = le32toh(object->reg);
val = le32toh(object->val);
pr_debug("%s: object=0x%04zx reg=0x%04x - val=0x%08x\n",
pr_debug("%s: offset=0x%04zx reg=0x%04x - val=0x%08x\n",
__func__,
(void *)object - iter->start,
reg, val);
@@ -124,7 +115,7 @@ do_dev_coredump_read_ring(const struct mcp251xfd_priv *priv,
key = le32toh(object->reg);
val = le32toh(object->val);
pr_debug("%s: reg=0x%04zx key=0x%02x: %8s - val=0x%08x\n",
pr_debug("%s: offset=0x%04zx key=0x%02x: %8s - val=0x%08x\n",
__func__,
(void *)object - iter->start,
key, get_ring_key_str(key), val);
@@ -152,7 +143,7 @@ do_dev_coredump_read_ring(const struct mcp251xfd_priv *priv,
ring->obj_size = val;
break;
default:
return -EINVAL;
continue;
}
}
@@ -175,6 +166,7 @@ do_dev_coredump_read(struct mcp251xfd_priv *priv,
le32toh(iter->hdr->magic) == MCP251XFD_DUMP_MAGIC) {
const struct mcp251xfd_dump_object_header *hdr = iter->hdr;
enum mcp251xfd_dump_object_type object_type;
struct mcp251xfd_ring ring;
size_t object_offset, object_len;
int err;
@@ -188,6 +180,8 @@ do_dev_coredump_read(struct mcp251xfd_priv *priv,
iter->object_start = iter->start + object_offset;
iter->object_end = iter->object_start + object_len;
mcp251xfd_dump_ring_init(&ring);
pr_debug("%s: hdr=0x%04zx type=0x%08x: %8s - offset=0x%04zx len=0x%04zx end=0x%04zx\n",
__func__,
(void *)iter->hdr - iter->start,
@@ -199,13 +193,17 @@ do_dev_coredump_read(struct mcp251xfd_priv *priv,
err = do_dev_coredump_read_reg(priv, iter, mem);
break;
case MCP251XFD_DUMP_OBJECT_TYPE_TEF:
err = do_dev_coredump_read_ring(priv, iter, priv->tef);
break;
case MCP251XFD_DUMP_OBJECT_TYPE_RX:
err = do_dev_coredump_read_ring(priv, iter, priv->rx);
break;
case MCP251XFD_DUMP_OBJECT_TYPE_TX:
err = do_dev_coredump_read_ring(priv, iter, priv->tx);
err = do_dev_coredump_read_ring(priv, iter, &ring);
if (err)
return err;
if (ring.fifo_nr >= ARRAY_SIZE(priv->ring))
return -EINVAL;
priv->ring[ring.fifo_nr] = ring;
break;
case MCP251XFD_DUMP_OBJECT_TYPE_END:
return 0;
+11 -17
View File
@@ -12,14 +12,17 @@
#include "mcp251xfd.h"
#include "mcp251xfd-dump.h"
#define MCP251XFD_TX_FIFO 1
#define MCP251XFD_RX_FIFO(x) (MCP251XFD_TX_FIFO + 1 + (x))
#define MCP251XFD_DUMP_UNKNOWN (-1U)
struct mcp251xfd_mem {
char buf[0x1000];
};
struct mcp251xfd_ring {
enum mcp251xfd_dump_object_type type;
const struct mcp251xfd_dump_regs_fifo *fifo;
void *ram;
unsigned int head;
unsigned int tail;
@@ -30,25 +33,14 @@ struct mcp251xfd_ring {
u8 obj_size;
};
#define MCP251XFD_RING_TEF 0
struct mcp251xfd_priv {
struct regmap *map;
struct mcp251xfd_ring tef[1];
struct mcp251xfd_ring tx[1];
struct mcp251xfd_ring rx[1];
u8 rx_ring_num;
struct mcp251xfd_ring ring[32];
};
static inline u8 mcp251xfd_get_ring_head(const struct mcp251xfd_ring *ring)
{
return ring->head & (ring->obj_num - 1);
}
static inline u8 mcp251xfd_get_ring_tail(const struct mcp251xfd_ring *ring)
{
return ring->tail & (ring->obj_num - 1);
}
void mcp251xfd_dump_ring_init(struct mcp251xfd_ring *ring);
void mcp251xfd_dump(struct mcp251xfd_priv *priv);
int mcp251xfd_dev_coredump_read(struct mcp251xfd_priv *priv,
@@ -57,5 +49,7 @@ int mcp251xfd_dev_coredump_read(struct mcp251xfd_priv *priv,
int mcp251xfd_regmap_read(struct mcp251xfd_priv *priv,
struct mcp251xfd_mem *mem,
const char *file_path);
const char *
get_object_type_str(enum mcp251xfd_dump_object_type object_type);
#endif
+329 -302
View File
@@ -2,7 +2,7 @@
//
// Microchip MCP251xFD Family CAN controller debug tool
//
// Copyright (c) 2019, 2020, 2021 Pengutronix,
// Copyright (c) 2019, 2020, 2021, 2022 Pengutronix,
// Marc Kleine-Budde <kernel@pengutronix.de>
//
@@ -72,6 +72,18 @@ struct mcp251xfd_dump_regs_mcp251xfd {
u32 devid;
};
static bool
mcp251xfd_fifo_is_unused(const struct mcp251xfd_dump_regs_fifo *fifo)
{
return fifo->con == 0x00600000 && fifo->sta == 0x00000000;
}
static bool
mcp251xfd_fifo_is_rx(const struct mcp251xfd_dump_regs_fifo *fifo)
{
return !(fifo->con & MCP251XFD_REG_FIFOCON_TXEN);
}
#define __dump_bit(val, prefix, bit, desc) \
pr_info("%16s %s\t\t%s\n", __stringify(bit), \
(val) & prefix##_##bit ? "x" : " ", desc)
@@ -232,7 +244,7 @@ static void mcp251xfd_dump_reg_intf(const struct mcp251xfd_priv *priv, u32 val,
#define __create_dump_fifo_bitmask(fifo, name, description) \
static void mcp251xfd_dump_reg_##fifo(const struct mcp251xfd_priv *priv, u32 val, u16 addr) \
{ \
int i; \
size_t i; \
\
pr_info(__stringify(name) ": " __stringify(fifo) "(0x%03x)=0x%08x\n", addr, val); \
pr_info(description ":\n"); \
@@ -244,7 +256,7 @@ static void mcp251xfd_dump_reg_##fifo(const struct mcp251xfd_priv *priv, u32 val
pr_info("\t\t"); \
for (i = 0; i < sizeof(val); i++) { \
if (val & BIT(i)) \
pr_cont("%d ", i); \
pr_cont("%zd ", i); \
} \
\
pr_cont("\n"); \
@@ -318,6 +330,24 @@ static void mcp251xfd_dump_reg_osc(const struct mcp251xfd_priv *priv, u32 val, u
__dump_bit(val, MCP251XFD_REG_OSC, PLLEN, "PLL Enable");
}
static void mcp251xfd_dump_reg_iocon(const struct mcp251xfd_priv *priv, u32 val, u16 addr)
{
pr_info("IOCON: iocon(0x%03x)=0x%08x\n", addr, val);
__dump_bit(val, MCP251XFD_REG_IOCON, INTOD, "Interrupt pins Open Drain Mode (0: Push/Pull Output, 1: Open Drain Output)");
__dump_bit(val, MCP251XFD_REG_IOCON, SOF, "Start-Of-Frame signal (0: Clock on CLKO pin, 1: SOF signal on CLKO pin)");
__dump_bit(val, MCP251XFD_REG_IOCON, TXCANOD, "TXCAN Open Drain Mode (0: Push/Pull Output, 1: Open Drain Output)");
__dump_bit(val, MCP251XFD_REG_IOCON, PM1, "GPIO Pin Mode (0: Interrupt Pin INT1 (RXIF), 1: Pin is used as GPIO1)");
__dump_bit(val, MCP251XFD_REG_IOCON, PM0, "GPIO Pin Mode (0: Interrupt Pin INT0 (TXIF), 1: Pin is used as GPIO0)");
__dump_bit(val, MCP251XFD_REG_IOCON, GPIO1, "GPIO1 Status");
__dump_bit(val, MCP251XFD_REG_IOCON, GPIO0, "GPIO0 Status");
__dump_bit(val, MCP251XFD_REG_IOCON, LAT1, "GPIO1 Latch");
__dump_bit(val, MCP251XFD_REG_IOCON, LAT0, "GPIO0 Latch");
__dump_bit(val, MCP251XFD_REG_IOCON, XSTBYEN, "Enable Transceiver Standby Pin Control");
__dump_bit(val, MCP251XFD_REG_IOCON, TRIS1, "GPIO1 Data Direction (0: Output Pin, 1: Input Pin)");
__dump_bit(val, MCP251XFD_REG_IOCON, TRIS0, "GPIO0 Data Direction (0: Output Pin, 1: Input Pin)");
}
static void mcp251xfd_dump_reg_tefcon(const struct mcp251xfd_priv *priv, u32 val, u16 addr)
{
pr_info("TEFCON: tefcon(0x%03x)=0x%08x\n", addr, val);
@@ -408,6 +438,8 @@ mcp251xfd_dump_regs(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs *regs,
const struct mcp251xfd_dump_regs_mcp251xfd *regs_mcp251xfd)
{
unsigned int i;
netdev_info(priv->ndev, "-------------------- register dump --------------------\n");
__dump_call(regs, con);
__dump_call(regs, nbtcfg);
@@ -425,29 +457,46 @@ mcp251xfd_dump_regs(const struct mcp251xfd_priv *priv,
__dump_call(regs, bdiag0);
__dump_call(regs, bdiag1);
__dump_call(regs_mcp251xfd, osc);
pr_info("-------------------- TEF --------------------\n");
__dump_call(regs, tefcon);
__dump_call(regs, tefsta);
__dump_call(regs, tefua);
pr_info("-------------------- TX_FIFO --------------------\n");
__dump_call_fifo(fifocon, fifo[MCP251XFD_TX_FIFO].con);
__dump_call_fifo(fifosta, fifo[MCP251XFD_TX_FIFO].sta);
__dump_call_fifo(fifoua, fifo[MCP251XFD_TX_FIFO].ua);
pr_info(" -------------------- RX_FIFO --------------------\n");
__dump_call_fifo(fifocon, fifo[MCP251XFD_RX_FIFO(0)].con);
__dump_call_fifo(fifosta, fifo[MCP251XFD_RX_FIFO(0)].sta);
__dump_call_fifo(fifoua, fifo[MCP251XFD_RX_FIFO(0)].ua);
netdev_info(priv->ndev, "------------------------- end -------------------------\n");
__dump_call(regs_mcp251xfd, iocon);
for (i = 0; i < ARRAY_SIZE(regs->fifo); i++) {
const struct mcp251xfd_dump_regs_fifo *fifo = &regs->fifo[i];
if (mcp251xfd_fifo_is_unused(fifo))
continue;
pr_info("----------------------- FIFO %2d - ", i);
if (i == 0) {
pr_info("TEF -----------------\n");
__dump_call(regs, tefcon);
__dump_call(regs, tefsta);
__dump_call(regs, tefua);
} else {
if (mcp251xfd_fifo_is_rx(fifo))
pr_info("RX ------------------\n");
else
pr_info("TX ------------------\n");
__dump_call_fifo(fifocon, fifo[i].con);
__dump_call_fifo(fifosta, fifo[i].sta);
__dump_call_fifo(fifoua, fifo[i].ua);
}
}
netdev_info(priv->ndev, "----------------------- end ---------------------------\n");
}
#undef __dump_call
#undef __dump_call_fifo
static u8 mcp251xfd_dump_get_fifo_size(const struct mcp251xfd_priv *priv, const struct mcp251xfd_dump_regs *regs, u32 fifo_con)
static u8
mcp251xfd_dump_get_fifo_size(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs_fifo *regs_fifo)
{
u8 obj_size;
obj_size = FIELD_GET(MCP251XFD_REG_FIFOCON_PLSIZE_MASK, fifo_con);
obj_size = FIELD_GET(MCP251XFD_REG_FIFOCON_PLSIZE_MASK, regs_fifo->con);
switch (obj_size) {
case MCP251XFD_REG_FIFOCON_PLSIZE_8:
return 8;
@@ -470,16 +519,91 @@ static u8 mcp251xfd_dump_get_fifo_size(const struct mcp251xfd_priv *priv, const
return 0;
}
static u8 mcp251xfd_dump_get_fifo_obj_num(const struct mcp251xfd_priv *priv, const struct mcp251xfd_dump_regs *regs, u32 fifo_con)
static u8
mcp251xfd_dump_get_tef_obj_size(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs_fifo *fifo)
{
return sizeof(struct mcp251xfd_hw_tef_obj);
}
static u8
mcp251xfd_dump_get_rx_obj_size(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs_fifo *fifo)
{
return sizeof(struct mcp251xfd_hw_rx_obj_can) -
sizeof_field(struct mcp251xfd_hw_rx_obj_can, data) +
mcp251xfd_dump_get_fifo_size(priv, fifo);
}
static u8
mcp251xfd_dump_get_tx_obj_size(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs_fifo *fifo)
{
return sizeof(struct mcp251xfd_hw_tx_obj_can) -
sizeof_field(struct mcp251xfd_hw_tx_obj_can, data) +
mcp251xfd_dump_get_fifo_size(priv, fifo);
}
static u8
mcp251xfd_dump_get_fifo_obj_num(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs_fifo *fifo)
{
u8 obj_num;
obj_num = FIELD_GET(MCP251XFD_REG_FIFOCON_FSIZE_MASK, fifo_con);
obj_num = FIELD_GET(MCP251XFD_REG_FIFOCON_FSIZE_MASK, fifo->con);
return obj_num + 1;
}
static void mcp251xfd_dump_ram_fifo_obj_data(const struct mcp251xfd_priv *priv, const u8 *data, u8 dlc)
static u16
mcp251xfd_dump_get_ring_obj_addr(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_ring *ring,
u8 n)
{
return ring->base + ring->obj_size * n;
}
static void *
mcp251xfd_dump_get_ring_hw_obj(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_ring *ring,
u8 n)
{
return ring->ram + ring->obj_size * n;
}
static u8
mcp251xfd_dump_get_ring_head(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_ring *ring)
{
return ring->head & (ring->obj_num - 1);
}
static u8
mcp251xfd_dump_get_ring_tail(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_ring *ring)
{
return ring->tail & (ring->obj_num - 1);
}
static u8
mcp251xfd_dump_get_chip_head(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_ring *ring)
{
return FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK,
ring->fifo->sta);
}
static u8
mcp251xfd_dump_get_chip_tail(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_ring *ring)
{
return (ring->fifo->ua -
(ring->base - MCP251XFD_RAM_START)) / ring->obj_size;
}
static void
mcp251xfd_dump_ring_obj_data(const struct mcp251xfd_priv *priv,
const u8 *data, u8 dlc)
{
int i;
u8 len;
@@ -510,326 +634,228 @@ static void mcp251xfd_dump_ram_fifo_obj_data(const struct mcp251xfd_priv *priv,
pr_cont("\n");
}
/* TEF */
static u8
mcp251xfd_dump_get_tef_obj_num(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs *regs)
static void
mcp251xfd_dump_analyze_regs_and_ram(struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs *regs,
const struct mcp251xfd_dump_ram *ram)
{
return mcp251xfd_dump_get_fifo_obj_num(priv, regs, regs->tef.con);
u16 base = MCP251XFD_RAM_START;
u8 ring_nr_rx = 0, ring_nr_tx = 0;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(regs->fifo); i++) {
const struct mcp251xfd_dump_regs_fifo *fifo;
struct mcp251xfd_ring *ring = &priv->ring[i];
if (i == MCP251XFD_RING_TEF) {
/* FIFO 0 is the TXQ, but it's unused by the driver
* put TEF here to make things easier.
*/
fifo = &regs->tef;
ring->type = MCP251XFD_DUMP_OBJECT_TYPE_TEF;
ring->nr = 0;
ring->obj_size = mcp251xfd_dump_get_tef_obj_size(priv, fifo);
} else {
fifo = &regs->fifo[i];
if (mcp251xfd_fifo_is_unused(fifo)) {
continue;
} else if (mcp251xfd_fifo_is_rx(fifo)) {
ring->type = MCP251XFD_DUMP_OBJECT_TYPE_RX;
ring->nr = ring_nr_rx++;
ring->obj_size = mcp251xfd_dump_get_rx_obj_size(priv, fifo);
} else {
ring->type = MCP251XFD_DUMP_OBJECT_TYPE_TX;
ring->nr = ring_nr_tx++;
ring->obj_size = mcp251xfd_dump_get_tx_obj_size(priv, fifo);
}
}
ring->fifo = fifo;
ring->ram = (void *)ram + (base - MCP251XFD_RAM_START);
ring->base = base;
ring->fifo_nr = i;
ring->obj_num = mcp251xfd_dump_get_fifo_obj_num(priv, fifo);
base = mcp251xfd_dump_get_ring_obj_addr(priv, ring, ring->obj_num);
}
printf("Found %u RX-FIFO%s, %u TX-FIFO%s\n\n",
ring_nr_rx, ring_nr_rx > 1 ? "s" : "",
ring_nr_tx, ring_nr_tx > 1 ? "s" : "");
}
static u8
mcp251xfd_dump_get_tef_tail(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs *regs)
static const char *
mcp251xfd_dump_ring_obj_one_fifo_flags_chip(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_ring *ring,
const u8 n)
{
return regs->tefua / sizeof(struct mcp251xfd_hw_tef_obj);
if (mcp251xfd_dump_get_chip_tail(priv, ring) != n)
return "";
if (ring->type == MCP251XFD_DUMP_OBJECT_TYPE_TX) {
if (!(ring->fifo->sta & MCP251XFD_REG_FIFOSTA_TFNRFNIF))
return " chip-FIFO-full";
if (ring->fifo->sta & MCP251XFD_REG_FIFOSTA_TFERFFIF)
return " chip-FIFO-empty";
} else {
if (ring->fifo->sta & MCP251XFD_REG_FIFOSTA_TFERFFIF)
return " chip-FIFO-full";
if (!(ring->fifo->sta & MCP251XFD_REG_FIFOSTA_TFNRFNIF))
return " chip-FIFO-empty";
}
return "";
}
static u16
mcp251xfd_dump_get_tef_obj_rel_addr(const struct mcp251xfd_priv *priv,
u8 n)
static const char *
mcp251xfd_dump_ring_obj_one_fifo_flags_ring(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_ring *ring,
const u8 n)
{
return sizeof(struct mcp251xfd_hw_tef_obj) * n;
if (ring->head == MCP251XFD_DUMP_UNKNOWN ||
ring->tail == MCP251XFD_DUMP_UNKNOWN ||
mcp251xfd_dump_get_ring_tail(priv, ring) != n ||
mcp251xfd_dump_get_ring_head(priv, ring) != mcp251xfd_dump_get_ring_tail(priv, ring))
return "";
if (ring->head == ring->tail)
return " ring-FIFO-empty";
else
return " ring-FIFO-full";
return "";
}
static u16
mcp251xfd_dump_get_tef_obj_addr(const struct mcp251xfd_priv *priv,
u8 n)
{
return mcp251xfd_dump_get_tef_obj_rel_addr(priv, n) +
MCP251XFD_RAM_START;
}
/* TX */
static u8
mcp251xfd_dump_get_tx_obj_size(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs *regs)
{
return sizeof(struct mcp251xfd_hw_tx_obj_can) -
sizeof_field(struct mcp251xfd_hw_tx_obj_can, data) +
mcp251xfd_dump_get_fifo_size(priv, regs, regs->tx_fifo.con);
}
static u8
mcp251xfd_dump_get_tx_obj_num(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs *regs)
{
return mcp251xfd_dump_get_fifo_obj_num(priv, regs, regs->tx_fifo.con);
}
static u16
mcp251xfd_dump_get_tx_obj_rel_addr(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs *regs,
u8 n)
{
return mcp251xfd_dump_get_tef_obj_rel_addr(priv, mcp251xfd_dump_get_tef_obj_num(priv, regs)) +
mcp251xfd_dump_get_tx_obj_size(priv, regs) * n;
}
static u16
mcp251xfd_dump_get_tx_obj_addr(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs *regs, u8 n)
{
return mcp251xfd_dump_get_tx_obj_rel_addr(priv, regs, n) +
MCP251XFD_RAM_START;
}
static u8
mcp251xfd_dump_get_tx_tail(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs *regs)
{
return (regs->fifo[MCP251XFD_TX_FIFO].ua -
mcp251xfd_dump_get_tx_obj_rel_addr(priv, regs, 0)) /
mcp251xfd_dump_get_tx_obj_size(priv, regs);
}
static u8
mcp251xfd_dump_get_tx_head(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs *regs)
{
return FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK,
regs->fifo[MCP251XFD_TX_FIFO].sta);
}
/* RX */
static u8
mcp251xfd_dump_get_rx_obj_size(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs *regs)
{
return sizeof(struct mcp251xfd_hw_rx_obj_can) -
sizeof_field(struct mcp251xfd_hw_rx_obj_can, data) +
mcp251xfd_dump_get_fifo_size(priv, regs, regs->rx_fifo.con);
}
static u8
mcp251xfd_dump_get_rx_obj_num(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs *regs)
{
return mcp251xfd_dump_get_fifo_obj_num(priv, regs, regs->rx_fifo.con);
}
static u16
mcp251xfd_dump_get_rx_obj_rel_addr(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs *regs, u8 n)
{
return mcp251xfd_dump_get_tx_obj_rel_addr(priv, regs, mcp251xfd_dump_get_tx_obj_num(priv, regs)) +
mcp251xfd_dump_get_rx_obj_size(priv, regs) * n;
}
static u16
mcp251xfd_dump_get_rx_obj_addr(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs *regs, u8 n)
{
return mcp251xfd_dump_get_rx_obj_rel_addr(priv, regs, n) + MCP251XFD_RAM_START;
}
static u8
mcp251xfd_dump_get_rx_tail(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs *regs)
{
return (regs->fifo[MCP251XFD_RX_FIFO(0)].ua -
mcp251xfd_dump_get_rx_obj_rel_addr(priv, regs, 0)) /
mcp251xfd_dump_get_rx_obj_size(priv, regs);
}
static u8
mcp251xfd_dump_get_rx_head(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs *regs)
{
return FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK, regs->fifo[MCP251XFD_RX_FIFO(0)].sta);
}
/* dump TEF */
static void
mcp251xfd_dump_ram_tef_obj_one(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs *regs,
const struct mcp251xfd_ring *tef,
const struct mcp251xfd_hw_tef_obj *hw_tef_obj,
u8 n)
mcp251xfd_dump_ring_obj_one(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_ring *ring,
const void *hw_obj, const u8 n)
{
pr_info("TEF Object: 0x%02x (0x%03x)%s%s%s%s%s\n",
n, mcp251xfd_dump_get_tef_obj_addr(priv, n),
mcp251xfd_get_ring_head(tef) == n ? " priv-HEAD" : "",
mcp251xfd_dump_get_tef_tail(priv, regs) == n ? " chip-TAIL" : "",
mcp251xfd_get_ring_tail(tef) == n ? " priv-TAIL" : "",
(mcp251xfd_dump_get_tef_tail(priv, regs) == n ?
((regs->tef.sta & MCP251XFD_REG_TEFSTA_TEFFIF) ? " chip-FIFO-full" :
!(regs->tef.sta & MCP251XFD_REG_TEFSTA_TEFNEIF) ? " chip-FIFO-empty" : "") :
("")),
(mcp251xfd_get_ring_head(tef) == mcp251xfd_get_ring_tail(tef) &&
mcp251xfd_get_ring_tail(tef) == n ?
(priv->tef->head == priv->tef->tail ? " priv-FIFO-empty" : " priv-FIFO-full") :
("")));
const struct mcp251xfd_hw_tef_obj *hw_tef_obj = hw_obj;
const struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj = hw_obj;
const struct mcp251xfd_hw_tx_obj_canfd *hw_tx_obj = hw_obj;
pr_info("%s-%d Object: "
"0x%02x (0x%03x)"
"%s%s%s%s%s%s"
"\n",
get_object_type_str(ring->type), ring->nr,
n, mcp251xfd_dump_get_ring_obj_addr(priv, ring, n),
ring->type != MCP251XFD_DUMP_OBJECT_TYPE_TEF && mcp251xfd_dump_get_chip_head(priv, ring) == n ? " chip-HEAD" : "",
ring->head != MCP251XFD_DUMP_UNKNOWN && mcp251xfd_dump_get_ring_head(priv, ring) == n ? " ring-HEAD" : "",
mcp251xfd_dump_get_chip_tail(priv, ring) == n ? " chip-TAIL" : "",
ring->tail != MCP251XFD_DUMP_UNKNOWN && mcp251xfd_dump_get_ring_tail(priv, ring) == n ? " ring-TAIL" : "",
mcp251xfd_dump_ring_obj_one_fifo_flags_chip(priv, ring, n),
mcp251xfd_dump_ring_obj_one_fifo_flags_ring(priv, ring, n)
);
pr_info("%16s = 0x%08x\n", "id", hw_tef_obj->id);
pr_info("%16s = 0x%08x\n", "flags", hw_tef_obj->flags);
pr_info("%16s = 0x%08x\n", "ts", hw_tef_obj->ts);
__dump_mask(hw_tef_obj->flags, MCP251XFD_OBJ_FLAGS, SEQ, "0x%06lx", "Sequence");
pr_info("\n");
}
static void
mcp251xfd_dump_ram_tef_obj(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs *regs,
const struct mcp251xfd_dump_ram *ram,
const struct mcp251xfd_ring *tef)
{
int i;
if (ring->type == MCP251XFD_DUMP_OBJECT_TYPE_TEF ||
ring->type == MCP251XFD_DUMP_OBJECT_TYPE_RX)
pr_info("%16s = 0x%08x\n", "ts", hw_tef_obj->ts);
pr_info("\nTEF Overview:\n");
pr_info("%16s = 0x%02x 0x%08x\n", "head (p)",
mcp251xfd_get_ring_head(tef),
tef->head);
pr_info("%16s = 0x%02x 0x%02x 0x%08x\n", "tail (c/p)",
mcp251xfd_dump_get_tef_tail(priv, regs),
mcp251xfd_get_ring_tail(tef),
tef->tail);
pr_info("\n");
for (i = 0; i < mcp251xfd_dump_get_tef_obj_num(priv, regs); i++) {
const struct mcp251xfd_hw_tef_obj *hw_tef_obj;
u16 hw_tef_obj_rel_addr;
hw_tef_obj_rel_addr = mcp251xfd_dump_get_tef_obj_rel_addr(priv, i);
hw_tef_obj = (const struct mcp251xfd_hw_tef_obj *)&ram->ram[hw_tef_obj_rel_addr];
mcp251xfd_dump_ram_tef_obj_one(priv, regs, tef, hw_tef_obj, i);
if (ring->type == MCP251XFD_DUMP_OBJECT_TYPE_TEF) {
__dump_mask(hw_tef_obj->flags, MCP251XFD_OBJ_FLAGS, SEQ, "0x%06lx", "Sequence");
} else if (ring->type == MCP251XFD_DUMP_OBJECT_TYPE_TX) {
__dump_mask(hw_tx_obj->flags, MCP251XFD_OBJ_FLAGS, SEQ_MCP2517FD, "0x%06lx", "Sequence (MCP2517)");
__dump_mask(hw_tx_obj->flags, MCP251XFD_OBJ_FLAGS, SEQ_MCP2518FD, "0x%06lx", "Sequence (MCP2518)");
}
}
/* dump TX */
if (ring->type == MCP251XFD_DUMP_OBJECT_TYPE_RX ||
ring->type == MCP251XFD_DUMP_OBJECT_TYPE_TX) {
const u8* data;
u8 dlc;
static void
mcp251xfd_dump_ram_tx_obj_one(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs *regs,
const struct mcp251xfd_ring *tx,
const struct mcp251xfd_hw_tx_obj_canfd *hw_tx_obj,
u8 n)
{
pr_info("TX Object: 0x%02x (0x%03x)%s%s%s%s%s%s\n",
n, mcp251xfd_dump_get_tx_obj_addr(priv, regs, n),
mcp251xfd_dump_get_tx_head(priv, regs) == n ? " chip-HEAD" : "",
mcp251xfd_get_ring_head(tx) == n ? " priv-HEAD" : "",
mcp251xfd_dump_get_tx_tail(priv, regs) == n ? " chip-TAIL" : "",
mcp251xfd_get_ring_tail(tx) == n ? " priv-TAIL" : "",
mcp251xfd_dump_get_tx_tail(priv, regs) == n ?
(!(regs->tx_fifo.sta & MCP251XFD_REG_FIFOSTA_TFNRFNIF) ? " chip-FIFO-full" :
(regs->tx_fifo.sta & MCP251XFD_REG_FIFOSTA_TFERFFIF) ? " chip-FIFO-empty" : "") :
(""),
(mcp251xfd_get_ring_head(tx) == mcp251xfd_get_ring_tail(tx) &&
mcp251xfd_get_ring_tail(tx) == n ?
(tx->head == tx->tail ? " priv-FIFO-empty" : " priv-FIFO-full") :
("")));
pr_info("%16s = 0x%08x\n", "id", hw_tx_obj->id);
pr_info("%16s = 0x%08x\n", "flags", hw_tx_obj->flags);
__dump_mask(hw_tx_obj->flags, MCP251XFD_OBJ_FLAGS, SEQ_MCP2517FD, "0x%06lx", "Sequence (MCP2517)");
__dump_mask(hw_tx_obj->flags, MCP251XFD_OBJ_FLAGS, SEQ_MCP2518FD, "0x%06lx", "Sequence (MCP2518)");
mcp251xfd_dump_ram_fifo_obj_data(priv,
hw_tx_obj->data,
FIELD_GET(MCP251XFD_OBJ_FLAGS_DLC, hw_tx_obj->flags));
pr_info("\n");
}
if (ring->type == MCP251XFD_DUMP_OBJECT_TYPE_RX)
data = hw_rx_obj->data;
else
data = hw_tx_obj->data;
static void
mcp251xfd_dump_ram_tx_obj(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs *regs,
const struct mcp251xfd_dump_ram *ram,
const struct mcp251xfd_ring *tx)
{
int i;
pr_info("\nTX Overview:\n");
pr_info("%16s = 0x%02x 0x%02x 0x%08x\n", "head (c/p)",
mcp251xfd_dump_get_tx_head(priv, regs),
mcp251xfd_get_ring_head(tx),
tx->head);
pr_info("%16s = 0x%02x 0x%02x 0x%08x\n", "tail (c/p)",
mcp251xfd_dump_get_tx_tail(priv, regs),
mcp251xfd_get_ring_tail(tx),
tx->tail);
pr_info("\n");
for (i = 0; i < mcp251xfd_dump_get_tx_obj_num(priv, regs); i++) {
const struct mcp251xfd_hw_tx_obj_canfd *hw_tx_obj;
u16 hw_tx_obj_rel_addr;
hw_tx_obj_rel_addr = mcp251xfd_dump_get_tx_obj_rel_addr(priv, regs, i);
hw_tx_obj = (const struct mcp251xfd_hw_tx_obj_canfd *)&ram->ram[hw_tx_obj_rel_addr];
mcp251xfd_dump_ram_tx_obj_one(priv, regs, tx, hw_tx_obj, i);
dlc = FIELD_GET(MCP251XFD_OBJ_FLAGS_DLC, hw_rx_obj->flags);
mcp251xfd_dump_ring_obj_data(priv, data, dlc);
}
}
/* dump RX */
static void
mcp251xfd_dump_ram_rx_obj_one(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs *regs,
const struct mcp251xfd_ring *rx,
const struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj,
u8 n)
{
pr_info("RX Object: 0x%02x (0x%03x)%s%s%s%s%s%s\n",
n, mcp251xfd_dump_get_rx_obj_addr(priv, regs, n),
mcp251xfd_dump_get_rx_head(priv, regs) == n ? " chip-HEAD" : "",
mcp251xfd_get_ring_head(rx) == n ? " priv-HEAD" : "",
mcp251xfd_dump_get_rx_tail(priv, regs) == n ? " chip-TAIL" : "",
mcp251xfd_get_ring_tail(rx) == n ? " priv-TAIL" : "",
mcp251xfd_dump_get_rx_tail(priv, regs) == n ?
((regs->rx_fifo.sta & MCP251XFD_REG_FIFOSTA_TFERFFIF) ? " chip-FIFO-full" :
!(regs->rx_fifo.sta & MCP251XFD_REG_FIFOSTA_TFNRFNIF) ? " chip-FIFO-empty" : "") :
(""),
(mcp251xfd_get_ring_head(rx) == mcp251xfd_get_ring_tail(rx) &&
mcp251xfd_get_ring_tail(rx) == n ?
(priv->rx->head == priv->rx->tail ? " priv-FIFO-empty" : " priv-FIFO-full") :
("")));
pr_info("%16s = 0x%08x\n", "id", hw_rx_obj->id);
pr_info("%16s = 0x%08x\n", "flags", hw_rx_obj->flags);
pr_info("%16s = 0x%08x\n", "ts", hw_rx_obj->ts);
mcp251xfd_dump_ram_fifo_obj_data(priv, hw_rx_obj->data, FIELD_GET(MCP251XFD_OBJ_FLAGS_DLC, hw_rx_obj->flags));
pr_info("\n");
}
static void
mcp251xfd_dump_ram_rx_obj(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs *regs,
const struct mcp251xfd_dump_ram *ram,
const struct mcp251xfd_ring *rx)
mcp251xfd_dump_ring(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_ring *ring,
const struct mcp251xfd_dump_regs *regs)
{
int i;
pr_info("\nRX Overview:\n");
pr_info("%16s = 0x%02x 0x%02x 0x%08x\n", "head (c/p)",
mcp251xfd_dump_get_rx_head(priv, regs),
mcp251xfd_get_ring_head(rx), rx->head);
pr_info("%16s = 0x%02x 0x%02x 0x%08x\n", "tail (c/p)",
mcp251xfd_dump_get_rx_tail(priv, regs),
mcp251xfd_get_ring_tail(rx), rx->tail);
pr_info("\n%s-%d FIFO %d Overview:\n",
get_object_type_str(ring->type), ring->nr, ring->fifo_nr);
if (ring->type == MCP251XFD_DUMP_OBJECT_TYPE_TEF) {
if (ring->head == MCP251XFD_DUMP_UNKNOWN)
pr_info("%16s\n", "head ( / )");
else
pr_info("%16s = 0x%02x 0x%08x\n", "head ( /r)",
mcp251xfd_dump_get_ring_head(priv, ring),
ring->head);
} else {
if (ring->head == MCP251XFD_DUMP_UNKNOWN)
pr_info("%16s = 0x%02x\n", "head (c/ )",
mcp251xfd_dump_get_chip_head(priv, ring));
else
pr_info("%16s = 0x%02x 0x%02x 0x%08x\n", "head (c/r)",
mcp251xfd_dump_get_chip_head(priv, ring),
mcp251xfd_dump_get_ring_head(priv, ring),
ring->head);
}
if (ring->tail == MCP251XFD_DUMP_UNKNOWN)
pr_info("%16s = 0x%02x\n", "tail (c/ )",
mcp251xfd_dump_get_chip_tail(priv, ring));
else
pr_info("%16s = 0x%02x 0x%02x 0x%08x\n", "tail (c/r)",
mcp251xfd_dump_get_chip_tail(priv, ring),
mcp251xfd_dump_get_ring_tail(priv, ring),
ring->tail);
pr_info("\n");
for (i = 0; i < mcp251xfd_dump_get_rx_obj_num(priv, regs); i++) {
const struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj;
u16 hw_rx_obj_rel_addr;
for (i = 0; i < ring->obj_num; i++) {
void *hw_obj;
hw_rx_obj_rel_addr = mcp251xfd_dump_get_rx_obj_rel_addr(priv, regs, i);
hw_rx_obj = (const struct mcp251xfd_hw_rx_obj_canfd *)&ram->ram[hw_rx_obj_rel_addr];
mcp251xfd_dump_ram_rx_obj_one(priv, regs, rx, hw_rx_obj, i);
hw_obj = mcp251xfd_dump_get_ring_hw_obj(priv, ring, i);
mcp251xfd_dump_ring_obj_one(priv, ring, hw_obj, i);
}
}
#undef __dump_mask
#undef __dump_bit
static void mcp251xfd_dump_ram(const struct mcp251xfd_priv *priv, const struct mcp251xfd_dump_regs *regs, const struct mcp251xfd_dump_ram *ram)
static void
mcp251xfd_dump_ram(const struct mcp251xfd_priv *priv,
const struct mcp251xfd_dump_regs *regs,
const struct mcp251xfd_dump_ram *ram)
{
unsigned int i;
netdev_info(priv->ndev, "----------------------- RAM dump ----------------------\n");
mcp251xfd_dump_ram_tef_obj(priv, regs, ram, priv->tef);
mcp251xfd_dump_ram_tx_obj(priv, regs, ram, priv->tx);
mcp251xfd_dump_ram_rx_obj(priv, regs, ram, priv->rx);
for (i = 0; i < ARRAY_SIZE(regs->fifo); i++) {
const struct mcp251xfd_ring *ring = &priv->ring[i];
switch (ring->type) {
case MCP251XFD_DUMP_OBJECT_TYPE_TEF:
case MCP251XFD_DUMP_OBJECT_TYPE_RX:
case MCP251XFD_DUMP_OBJECT_TYPE_TX:
mcp251xfd_dump_ring(priv, ring, regs);
default:
break;
}
}
netdev_info(priv->ndev, "------------------------- end -------------------------\n");
}
@@ -858,6 +884,7 @@ void mcp251xfd_dump(struct mcp251xfd_priv *priv)
if (err)
return;
mcp251xfd_dump_analyze_regs_and_ram(priv, &regs, &ram);
mcp251xfd_dump_regs(priv, &regs, &regs_mcp251xfd);
mcp251xfd_dump_ram(priv, &regs, &ram);
}
+50
View File
@@ -0,0 +1,50 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
#
# Copyright (c) 2023 Pengutronix,
# Marc Kleine-Budde <kernel@pengutronix.de>
set -x
set -e
DEV=${1:-can0}
SPI=${2:-$(ethtool -i ${DEV}|sed -ne "s/bus-info: //p")}
modprobe -r mcp251xfd
modprobe mcp251xfd
sleep 2
ip link set ${DEV} down
sleep 2
rm -vf /var/log/devcoredump-*.dump
ip link set ${DEV} up type can bitrate 1000000 dbitrate 4000000 fd on restart-ms 1000 berr-reporting off listen-only off loopback on
ethtool -g ${DEV} || true
ethtool -c ${DEV} || true
cangen ${DEV} -Di -L8 -I2 -p 10 -g 200 -n 3
cat /sys/kernel/debug/regmap/${SPI}-crc/registers > data/registers-canfd.dump
ip link set ${DEV} down
sleep 2
cp -av /var/log/devcoredump-*.dump data
ip link set ${DEV} up type can bitrate 1000000 fd off restart-ms 1000 berr-reporting off listen-only off loopback on
rm -vf /var/log/devcoredump-*.dump
ethtool -g ${DEV} || true
ethtool -c ${DEV} || true
cangen ${DEV} -Di -L8 -I2 -p 10 -g 200 -n 7
cat /sys/kernel/debug/regmap/${SPI}-crc/registers > data/registers-classic-can.dump
ip link set ${DEV} down
sleep 2
cp -av /var/log/devcoredump-*.dump data
+16
View File
@@ -8,6 +8,7 @@
#include <errno.h>
#include <getopt.h>
#include <libgen.h>
#include <stdlib.h>
#include <string.h>
@@ -44,6 +45,17 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg,
return 0;
}
void mcp251xfd_dump_ring_init(struct mcp251xfd_ring *ring)
{
memset(ring, 0x0, sizeof(*ring));
ring->type = MCP251XFD_DUMP_UNKNOWN;
ring->head = MCP251XFD_DUMP_UNKNOWN;
ring->tail = MCP251XFD_DUMP_UNKNOWN;
ring->nr = (uint8_t)MCP251XFD_DUMP_UNKNOWN;
ring->fifo_nr = (uint8_t)MCP251XFD_DUMP_UNKNOWN;
}
int main(int argc, char *argv[])
{
struct mcp251xfd_mem mem = { };
@@ -54,6 +66,7 @@ int main(int argc, char *argv[])
.map = &map,
};
const char *file_path;
unsigned int i;
int opt, err;
struct option long_options[] = {
@@ -82,6 +95,9 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
for (i = 0; i < ARRAY_SIZE(priv.ring); i++)
mcp251xfd_dump_ring_init(&priv.ring[i]);
err = mcp251xfd_dev_coredump_read(&priv, &mem, file_path);
if (err)
err = mcp251xfd_regmap_read(&priv, &mem, file_path);
+21 -5
View File
@@ -2,7 +2,7 @@
//
// Microchip MCP251xFD Family CAN controller debug tool
//
// Copyright (c) 2020 Pengutronix,
// Copyright (c) 2020, 2022, 2023 Pengutronix,
// Marc Kleine-Budde <kernel@pengutronix.de>
//
@@ -26,21 +26,37 @@ do_mcp251xfd_regmap_read(struct mcp251xfd_priv *priv,
FILE *reg_file;
uint16_t reg;
uint32_t val;
unsigned int n = 0;
int ret, err = 0;
reg_file = fopen(file_path, "r");
if (!reg_file)
return -errno;
while (fscanf(reg_file, "%hx: %x\n", &reg, &val) == 2) {
if (reg >= ARRAY_SIZE(mem->buf))
return -EINVAL;
while ((ret = fscanf(reg_file, "%hx: %x\n", &reg, &val)) != EOF) {
if (ret != 2) {
fscanf(reg_file, "%*[^\n]\n");
continue;
}
if (reg >= ARRAY_SIZE(mem->buf)) {
err = -EINVAL;
goto out_close;
}
*(uint32_t *)(mem->buf + reg) = val;
n++;
}
printf("regmap: Found %u registers in %s\n", n, file_path);
if (!n)
err = -EINVAL;
out_close:
fclose(reg_file);
return 0;
return err;
}
int mcp251xfd_regmap_read(struct mcp251xfd_priv *priv,
+2 -2
View File
@@ -67,7 +67,7 @@ void print_usage(char *prg)
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, " -w (attach - wait for keypress - detach)\n");
fprintf(stderr, " -n <name> (assign created netdevice name)\n");
fprintf(stderr, "\n"
" <speed> Bitrate\n"
@@ -141,7 +141,7 @@ int main(int argc, char **argv)
case 'b':
btr = optarg;
if (strlen(btr) > 6)
if (strlen(btr) > 8)
print_usage(argv[0]);
break;
+1 -1
View File
@@ -246,7 +246,7 @@ int main(int argc, char *argv[])
break;
case 'b':
btr = optarg;
if (strlen(btr) > 6)
if (strlen(btr) > 8)
print_usage(argv[0]);
break;
case 'F':
+9 -22
View File
@@ -43,27 +43,12 @@
#include <linux/can/raw.h>
#include <linux/sockios.h>
#include "lib.h"
/* maximum rx buffer len: extended CAN frame with timestamp */
#define SLC_MTU (sizeof("T1111222281122334455667788EA5F\r")+1)
#define DEVICE_NAME_PTMX "/dev/ptmx"
#define DEBUG
static int asc2nibble(char c)
{
if ((c >= '0') && (c <= '9'))
return c - '0';
if ((c >= 'A') && (c <= 'F'))
return c - 'A' + 10;
if ((c >= 'a') && (c <= 'f'))
return c - 'a' + 10;
return 16; /* error */
}
/* read data from pty, send CAN frames to CAN socket and answer commands */
int pty2can(int pty, int socket, struct can_filter *fi,
int *is_open, int *tstamp)
@@ -119,14 +104,12 @@ rx_restart:
cmd = buf[0];
buf[nbytes] = 0;
#ifdef DEBUG
for (tmp = 0; tmp < nbytes; tmp++)
if (buf[tmp] == '\r')
putchar('@');
pr_debug("@");
else
putchar(buf[tmp]);
printf("\n");
#endif
pr_debug("%c", buf[tmp]);
pr_debug("\n");
/* check for filter configuration commands */
if (cmd == 'm' || cmd == 'M') {
@@ -501,6 +484,10 @@ int main(int argc, char **argv)
addr.can_family = AF_CAN;
addr.can_ifindex = if_nametoindex(argv[2]);
if (!addr.can_ifindex) {
perror("if_nametoindex");
return 1;
}
/* disable reception of CAN frames until we are opened by 'O' */
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
+1 -1
View File
@@ -36,7 +36,7 @@ static const char help_msg[] =
" -s[=LEN] Initial send of LEN bytes dummy data\n"
" -r Receive (and print) data\n"
" -e Echo incoming packets back\n"
" This atually receives packets\n"
" This actually receives packets\n"
" -c Issue connect()\n"
" -p=PRIO Set priority to PRIO\n"
" -P Promiscuous mode. Allow to receive all packets\n"