summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2005-08-25 15:39:17 +0000
committerSascha Hauer <s.hauer@pengutronix.de>2005-08-25 15:39:17 +0000
commitb837431cb0e6e88355d89b691f2ff65fc9f27514 (patch)
treee9a97e3acf34088441497ce98c5118def005d150
parent7c38bc259c2f5e7f52826c93f0218d0b2b964a94 (diff)
downloadcanutils-b837431cb0e6e88355d89b691f2ff65fc9f27514.tar.gz
canutils-b837431cb0e6e88355d89b691f2ff65fc9f27514.tar.xz
add cansequence tool
git-svn-id: https://iocaste.extern.pengutronix.de/svn/canutils/trunks/canutils-1.0-trunk@40 5fd5a299-6ef2-0310-aa18-8b01d7c39d8c
-rw-r--r--Makefile.am3
-rw-r--r--cansequence.c193
2 files changed, 195 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index 00db34f..ced7bc3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,4 @@
-bin_PROGRAMS = candump canecho cansend
+bin_PROGRAMS = candump canecho cansend cansequence
sbin_PROGRAMS = canconfig
SUBDIRS = include config
@@ -11,6 +11,7 @@ candump_SOURCES = candump.c
canecho_SOURCES = canecho.c
cansend_SOURCES = cansend.c
canconfig_SOURCES = canconfig.c
+cansequence_SOURCES = cansequence.c
EXTRA_DIST = \
autogen.sh \
diff --git a/cansequence.c b/cansequence.c
new file mode 100644
index 0000000..16a81b5
--- /dev/null
+++ b/cansequence.c
@@ -0,0 +1,193 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <libgen.h>
+#include <getopt.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+
+#include <socket-can/can.h>
+#include <can_config.h>
+
+extern int optind, opterr, optopt;
+
+static int s = -1;
+static int running = 1;
+
+enum
+{
+ VERSION_OPTION = CHAR_MAX + 1,
+};
+
+void print_usage(char *prg)
+{
+ fprintf(stderr, "Usage: %s <can-interface> [Options]\n"
+ "\n"
+ "cansequence sends CAN messages with a rising sequence number as payload.\n"
+ "When the -r option is given, cansequence expects to receive these messages\n"
+ "and prints an error message if a wrong sequence number is encountered.\n"
+ "The main purpose of this program is to test the reliability of CAN links.\n"
+ "\n"
+ "Options:\n"
+ " -f, --family=FAMILY Protocol family (default PF_CAN = %d)\n"
+ " -t, --type=TYPE Socket type, see man 2 socket (default SOCK_RAW = %d)\n"
+ " -p, --protocol=PROTO CAN protocol (default CAN_PROTO_RAW = %d)\n"
+ " -r, --receive work as receiver\n"
+ " -l --loop=COUNT send COUNT messages\n"
+ " -q --quit quit if a wrong sequence is encountered\n"
+ " -v, --verbose be verbose\n"
+ " -h --help this help\n"
+ " --version print version information and exit\n",
+ prg, PF_CAN, SOCK_RAW, CAN_PROTO_RAW);
+}
+
+void sigterm(int signo)
+{
+ running = 0;
+}
+
+int main(int argc, char **argv)
+{
+ int family = PF_CAN, type = SOCK_RAW, proto = CAN_PROTO_RAW;
+ int opt;
+ struct sockaddr_can addr;
+ struct can_frame frame;
+ int nbytes;
+ struct ifreq ifr;
+ int receive = 0;
+ int loopcount = 1, infinite = 1;
+ unsigned char sequence = 0;
+ int sequence_init = 1;
+ int verbose = 0, quit = 0;
+
+ signal(SIGTERM, sigterm);
+ signal(SIGHUP, sigterm);
+
+ struct option long_options[] = {
+ { "help", no_argument, 0, 'h' },
+ { "family", required_argument, 0, 'f' },
+ { "protocol", required_argument, 0, 'p' },
+ { "type", required_argument, 0, 't' },
+ { "version", no_argument, 0, VERSION_OPTION},
+ { "receive", no_argument, 0, 'r'},
+ { "quit", no_argument, 0, 'q'},
+ { "loop", required_argument, 0, 'l'},
+ { "verbose", no_argument, 0, 'v'},
+ { 0, 0, 0, 0},
+ };
+
+ while ((opt = getopt_long(argc, argv, "f:t:p:vrl:hq", long_options, NULL)) != -1) {
+ switch (opt) {
+ case 'h':
+ print_usage(basename(argv[0]));
+ exit(0);
+
+ case 'f':
+ family = strtoul(optarg, NULL, 0);
+ break;
+
+ case 't':
+ type = strtoul(optarg, NULL, 0);
+ break;
+
+ case 'p':
+ proto = strtoul(optarg, NULL, 0);
+ break;
+
+ case 'l':
+ loopcount = strtoul(optarg, NULL, 0);
+ infinite = 0;
+ break;
+
+ case 'r':
+ receive = 1;
+ break;
+
+ case 'q':
+ quit = 1;
+ break;
+
+ case 'v':
+ verbose = 1;
+ break;
+
+ case VERSION_OPTION:
+ printf("cansequence %s\n",VERSION);
+ exit(0);
+
+ default:
+ fprintf(stderr, "Unknown option %c\n", opt);
+ break;
+ }
+ }
+
+ if (optind == argc) {
+ print_usage(basename(argv[0]));
+ exit(0);
+ }
+
+ printf("interface = %s, family = %d, type = %d, proto = %d\n",
+ argv[optind], family, type, proto);
+ if ((s = socket(family, type, proto)) < 0) {
+ perror("socket");
+ return 1;
+ }
+
+ addr.can_family = family;
+ strncpy(ifr.ifr_name, argv[optind], sizeof(ifr.ifr_name));
+ ioctl(s, SIOCGIFINDEX, &ifr);
+ addr.can_ifindex = ifr.ifr_ifindex;
+ addr.can_id = CAN_FLAG_ALL;
+
+ if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ perror("bind");
+ return 1;
+ }
+
+ if(receive) {
+ while ((infinite || loopcount--) && running) {
+ if ((nbytes = read(s, &frame, sizeof(struct can_frame))) < 0) {
+ perror("read");
+ return 1;
+ } else {
+ if( sequence_init ) {
+ sequence_init = 0;
+ sequence = frame.payload.data[0];
+ }
+ if(verbose)
+ printf("received frame. sequence number: %d\n",sequence);
+ if( frame.payload.data[0] != sequence) {
+ printf("received wrong sequence count. expected: %d, got: %d\n",
+ frame.payload.data[0], sequence);
+ if(quit)
+ exit(1);
+ sequence = frame.payload.data[0];
+ }
+ sequence++;
+ }
+ }
+ } else {
+ frame.can_dlc = 1;
+ frame.can_id = 2;
+ frame.payload.data[0] = 0;
+ while ((infinite || loopcount--) && running) {
+ if(verbose)
+ printf("sending frame. sequence number: %d\n",sequence);
+ if( write(s, &frame, sizeof(frame)) < 0) {
+ perror("write");
+ break;
+ }
+ (unsigned char)frame.payload.data[0]++;
+ sequence++;
+// printf("%d %d\n",sequence,(unsigned char)frame.payload.data[0]);
+// usleep(10000);
+ }
+ }
+ return 0;
+}