From f811b53dfea1022def0961f7370effad4c784fba Mon Sep 17 00:00:00 2001 From: "Arnout Vandecappelle (Essensium/Mind)" Date: Tue, 21 Aug 2018 18:24:45 +0200 Subject: [PATCH 1/2] cansend: re-order socket handling and parsing of input Do all the socket handling (setting address, bind, socket options) in the beginning. Only parse the canframe argument after this is done. This has as effect that wrong arguments are only reported after the device has been opened and bound. This is preparation for sending multiple CAN frames in one cansend invocation. Signed-off-by: Arnout Vandecappelle (Essensium/Mind) --- cansend.c | 56 +++++++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/cansend.c b/cansend.c index b912e80..a9f189f 100644 --- a/cansend.c +++ b/cansend.c @@ -71,23 +71,6 @@ int main(int argc, char **argv) return 1; } - /* parse CAN frame */ - required_mtu = parse_canframe(argv[2], &frame); - if (!required_mtu){ - fprintf(stderr, "\nWrong CAN-frame format! Try:\n\n"); - fprintf(stderr, " #{R|data} for CAN 2.0 frames\n"); - fprintf(stderr, " ##{data} for CAN FD frames\n\n"); - fprintf(stderr, " can have 3 (SFF) or 8 (EFF) hex chars\n"); - fprintf(stderr, "{data} has 0..8 (0..64 CAN FD) ASCII hex-values (optionally"); - fprintf(stderr, " separated by '.')\n"); - fprintf(stderr, " a single ASCII Hex value (0 .. F) which defines"); - fprintf(stderr, " canfd_frame.flags\n\n"); - fprintf(stderr, "e.g. 5A1#11.2233.44556677.88 / 123#DEADBEEF / 5AA# / "); - fprintf(stderr, "123##1 / 213##311\n 1F334455#1122334455667788 / 123#R "); - fprintf(stderr, "for remote transmission request.\n\n"); - return 1; - } - /* open socket */ if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) { perror("socket"); @@ -106,6 +89,34 @@ int main(int argc, char **argv) addr.can_family = AF_CAN; 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. */ + setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0); + + if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + perror("bind"); + return 1; + } + + /* parse CAN frame */ + required_mtu = parse_canframe(argv[2], &frame); + if (!required_mtu){ + fprintf(stderr, "\nWrong CAN-frame format! Try:\n\n"); + fprintf(stderr, " #{R|data} for CAN 2.0 frames\n"); + fprintf(stderr, " ##{data} for CAN FD frames\n\n"); + fprintf(stderr, " can have 3 (SFF) or 8 (EFF) hex chars\n"); + fprintf(stderr, "{data} has 0..8 (0..64 CAN FD) ASCII hex-values (optionally"); + fprintf(stderr, " separated by '.')\n"); + fprintf(stderr, " a single ASCII Hex value (0 .. F) which defines"); + fprintf(stderr, " canfd_frame.flags\n\n"); + fprintf(stderr, "e.g. 5A1#11.2233.44556677.88 / 123#DEADBEEF / 5AA# / "); + fprintf(stderr, "123##1 / 213##311\n 1F334455#1122334455667788 / 123#R "); + fprintf(stderr, "for remote transmission request.\n\n"); + return 1; + } + if (required_mtu > CAN_MTU) { /* check if the frame fits into the CAN netdevice */ @@ -131,17 +142,6 @@ int main(int argc, char **argv) frame.len = can_dlc2len(can_len2dlc(frame.len)); } - /* 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 (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - perror("bind"); - return 1; - } - /* send frame */ if (write(s, &frame, required_mtu) != required_mtu) { perror("write"); From b541771b7b9caac2fdfd5f5c9603f0c7702e1195 Mon Sep 17 00:00:00 2001 From: "Arnout Vandecappelle (Essensium/Mind)" Date: Tue, 21 Aug 2018 18:37:10 +0200 Subject: [PATCH 2/2] cansend: send multiple frames in one invocation It is sometimes convenient to be able to send multiple frames with a single cansend invocation, otherwise the time between frames can get very large. Signed-off-by: Arnout Vandecappelle (Essensium/Mind) --- README.md | 2 +- cansend.c | 94 +++++++++++++++++++++++++++++-------------------------- 2 files changed, 51 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 06178d8..3e8c22d 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ subsystem (aka SocketCAN): * candump : display, filter and log CAN data to files * canplayer : replay CAN logfiles -* cansend : send a single frame +* cansend : send single frames * cangen : generate (random) CAN traffic * cansniffer : display CAN data content differences (just 11bit CAN IDs) diff --git a/cansend.c b/cansend.c index a9f189f..5b9e2b7 100644 --- a/cansend.c +++ b/cansend.c @@ -60,14 +60,15 @@ int main(int argc, char **argv) int s; /* can raw socket */ int required_mtu; int mtu; - int enable_canfd = 1; + int enable_canfd = 0; + int framecnt; struct sockaddr_can addr; struct canfd_frame frame; struct ifreq ifr; /* check command line options */ - if (argc != 3) { - fprintf(stderr, "Usage: %s .\n", argv[0]); + if (argc < 3) { + fprintf(stderr, "Usage: %s ...\n", argv[0]); return 1; } @@ -100,52 +101,57 @@ int main(int argc, char **argv) return 1; } - /* parse CAN frame */ - required_mtu = parse_canframe(argv[2], &frame); - if (!required_mtu){ - fprintf(stderr, "\nWrong CAN-frame format! Try:\n\n"); - fprintf(stderr, " #{R|data} for CAN 2.0 frames\n"); - fprintf(stderr, " ##{data} for CAN FD frames\n\n"); - fprintf(stderr, " can have 3 (SFF) or 8 (EFF) hex chars\n"); - fprintf(stderr, "{data} has 0..8 (0..64 CAN FD) ASCII hex-values (optionally"); - fprintf(stderr, " separated by '.')\n"); - fprintf(stderr, " a single ASCII Hex value (0 .. F) which defines"); - fprintf(stderr, " canfd_frame.flags\n\n"); - fprintf(stderr, "e.g. 5A1#11.2233.44556677.88 / 123#DEADBEEF / 5AA# / "); - fprintf(stderr, "123##1 / 213##311\n 1F334455#1122334455667788 / 123#R "); - fprintf(stderr, "for remote transmission request.\n\n"); - return 1; - } - - if (required_mtu > CAN_MTU) { - - /* check if the frame fits into the CAN netdevice */ - if (ioctl(s, SIOCGIFMTU, &ifr) < 0) { - perror("SIOCGIFMTU"); - return 1; - } - mtu = ifr.ifr_mtu; - - if (mtu != CANFD_MTU) { - printf("CAN interface is not CAN FD capable - sorry.\n"); + for (framecnt = 2; framecnt < argc; framecnt++) { + /* parse CAN frame */ + required_mtu = parse_canframe(argv[framecnt], &frame); + if (!required_mtu){ + fprintf(stderr, "\nWrong CAN-frame format! Try:\n\n"); + fprintf(stderr, " #{R|data} for CAN 2.0 frames\n"); + fprintf(stderr, " ##{data} for CAN FD frames\n\n"); + fprintf(stderr, " can have 3 (SFF) or 8 (EFF) hex chars\n"); + fprintf(stderr, "{data} has 0..8 (0..64 CAN FD) ASCII hex-values (optionally"); + fprintf(stderr, " separated by '.')\n"); + fprintf(stderr, " a single ASCII Hex value (0 .. F) which defines"); + fprintf(stderr, " canfd_frame.flags\n\n"); + fprintf(stderr, "e.g. 5A1#11.2233.44556677.88 / 123#DEADBEEF / 5AA# / "); + fprintf(stderr, "123##1 / 213##311\n 1F334455#1122334455667788 / 123#R "); + fprintf(stderr, "for remote transmission request.\n\n"); return 1; } - /* 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))){ - printf("error when enabling CAN FD support\n"); - return 1; + if (required_mtu > CAN_MTU) { + + if (enable_canfd == 0) { + /* check if the frame fits into the CAN netdevice */ + if (ioctl(s, SIOCGIFMTU, &ifr) < 0) { + perror("SIOCGIFMTU"); + return 1; + } + mtu = ifr.ifr_mtu; + + if (mtu != CANFD_MTU) { + printf("CAN interface is not CAN FD capable - sorry.\n"); + return 1; + } + + /* interface is ok - try to switch the socket into CAN FD mode */ + 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; + } + } + + /* ensure discrete CAN FD length values 0..8, 12, 16, 20, 24, 32, 64 */ + frame.len = can_dlc2len(can_len2dlc(frame.len)); } - /* ensure discrete CAN FD length values 0..8, 12, 16, 20, 24, 32, 64 */ - frame.len = can_dlc2len(can_len2dlc(frame.len)); - } - - /* send frame */ - if (write(s, &frame, required_mtu) != required_mtu) { - perror("write"); - return 1; + /* send frame */ + if (write(s, &frame, required_mtu) != required_mtu) { + perror("write"); + return 1; + } } close(s);