summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarc Kleine-Budde <mkl@pengutronix.de>2005-11-29 13:32:13 +0000
committerMarc Kleine-Budde <mkl@pengutronix.de>2005-11-29 13:32:13 +0000
commite7c603844d1a3af80f2d2aaac3c9c8e3674bccfe (patch)
treefe346bf498779fcb891cfa15b2cc86777e85d03c /src
parent6c317b329562fe898737fe3c7b516922e2f075f4 (diff)
downloadcanutils-e7c603844d1a3af80f2d2aaac3c9c8e3674bccfe.tar.gz
canutils-e7c603844d1a3af80f2d2aaac3c9c8e3674bccfe.tar.xz
* code restructured
git-svn-id: https://iocaste.extern.pengutronix.de/svn/canutils/trunks/canutils-1.0-trunk@54 5fd5a299-6ef2-0310-aa18-8b01d7c39d8c
Diffstat (limited to 'src')
-rw-r--r--src/GNUmakefile.am15
-rw-r--r--src/canconfig.c328
-rw-r--r--src/candump.c187
-rw-r--r--src/canecho.c147
-rw-r--r--src/cansend.c186
-rw-r--r--src/cansequence.c195
6 files changed, 1058 insertions, 0 deletions
diff --git a/src/GNUmakefile.am b/src/GNUmakefile.am
new file mode 100644
index 0000000..195532c
--- /dev/null
+++ b/src/GNUmakefile.am
@@ -0,0 +1,15 @@
+bin_PROGRAMS = \
+ candump \
+ canecho \
+ cansend \
+ cansequence
+
+sbin_PROGRAMS = \
+ canconfig
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/include
+ -I$(top_builddir)/include
+
+MAINTAINERCLEANFILES = \
+ GNUmakefile.in
diff --git a/src/canconfig.c b/src/canconfig.c
new file mode 100644
index 0000000..9207fe5
--- /dev/null
+++ b/src/canconfig.c
@@ -0,0 +1,328 @@
+/*
+ * canutils/canconfig.c
+ *
+ * Copyright (C) 2005 Marc Kleine-Budde <mkl@pengutronix.de>, Pengutronix
+ *
+ * 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
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/ether.h>
+
+#include <socket-can/can.h>
+
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+int s;
+struct ifreq ifr;
+
+struct speed_map {
+ unsigned short speed;
+ unsigned short value;
+};
+
+static const struct speed_map speeds[] = {
+ {CAN_BAUD_10K, 10},
+ {CAN_BAUD_20K, 20},
+ {CAN_BAUD_50K, 50},
+ {CAN_BAUD_100K, 100},
+ {CAN_BAUD_125K, 125},
+ {CAN_BAUD_250K, 250},
+ {CAN_BAUD_500K, 500},
+ {CAN_BAUD_800K, 800},
+ {CAN_BAUD_1M, 1000},
+};
+
+static const int NUM_SPEEDS = (sizeof(speeds) / sizeof(struct speed_map));
+
+unsigned long can_baud_to_value(speed_t speed)
+{
+ int i = 0;
+
+ do {
+ if (speed == speeds[i].speed) {
+ return speeds[i].value;
+ }
+ } while (++i < NUM_SPEEDS);
+
+ return 0;
+}
+
+speed_t can_value_to_baud(unsigned long value)
+{
+ int i = 0;
+
+ do {
+ if (value == can_baud_to_value(speeds[i].speed)) {
+ return speeds[i].speed;
+ }
+ } while (++i < NUM_SPEEDS);
+
+ return (speed_t)-1;
+}
+
+
+void help(void)
+{
+ fprintf(stderr, "usage:\n\t"
+ "canconfig <dev> baudrate { BR | BTR }\n\t\t"
+ "BR := { 10 | 20 | 50 | 100 | 125 | 250 | 500 | 800 | 1000 }\n\t\t"
+ "BTR := btr_sja1000 <brp> <sjw> <tseg1> <tseg2> <sam>\n\t\t"
+ "BTR := btr_c_can <brp> <sjw> <tseg1> <tseg2>\n\t\t"
+ "BTR := btr_nios <prescale> <timea> <timeb>\n\t"
+ "canconfig <dev> mode MODE\n\t\t"
+ "MODE := { start }\n\t"
+ "canconfig <dev> state\n"
+ );
+
+ exit(EXIT_FAILURE);
+}
+
+
+void do_show_baudrate(int argc, char* argv[])
+{
+ struct can_baudrate *br = (struct can_baudrate *)&ifr.ifr_ifru;
+ int i, value;
+
+ i = ioctl(s, SIOCGCANBAUDRATE, &ifr);
+ if (i < 0) {
+ perror("ioctl");
+ exit(EXIT_FAILURE);
+ }
+
+ switch (br->baudrate) {
+ case CAN_BAUD_BTR_SJA1000:
+ fprintf(stdout, "%s: sja1000 brp=%d sjw=%d tseg1=%d tseg2=%d sam=%d\n",
+ ifr.ifr_name,
+ br->btr.sja1000.brp,
+ br->btr.sja1000.sjw,
+ br->btr.sja1000.tseg1,
+ br->btr.sja1000.tseg2,
+ br->btr.sja1000.sam);
+ break;
+ case CAN_BAUD_BTR_C_CAN:
+ fprintf(stdout, "%s: C-Can brp=%d sjw=%d tseg1=%d tseg2=%d\n",
+ ifr.ifr_name,
+ br->btr.c_can.brp,
+ br->btr.c_can.sjw,
+ br->btr.c_can.tseg1,
+ br->btr.c_can.tseg2);
+ break;
+ case CAN_BAUD_BTR_NIOS:
+ fprintf(stdout, "%s: nios prescale=%d timea=%d timeb=%d\n",
+ ifr.ifr_name,
+ br->btr.nios.prescale,
+ br->btr.nios.timea,
+ br->btr.nios.timeb);
+ break;
+ default:
+ value = can_baud_to_value(br->baudrate);
+ if (value != 0)
+ fprintf(stdout,
+ "%s: baudrate %d\n", ifr.ifr_name, value);
+ else
+ fprintf(stdout, "baudrate not recognized. update canconfig?\n");
+ break;
+ }
+}
+
+
+void do_set_baudrate(int argc, char* argv[])
+{
+ struct can_baudrate *br = (struct can_baudrate *)&ifr.ifr_ifru;
+ speed_t baudrate;
+ int value, i;
+
+ if (!strcmp(argv[3], "btr_sja1000")) {
+ struct can_baudrate_sja1000 *br_sja1000 = &br->btr.sja1000;
+
+ if (argc < 9)
+ help();
+
+ br->baudrate = CAN_BAUD_BTR_SJA1000;
+ br_sja1000->brp = strtol(argv[4], NULL, 0);
+ br_sja1000->sjw = strtol(argv[5], NULL, 0);
+ br_sja1000->tseg1 = strtol(argv[6], NULL, 0);
+ br_sja1000->tseg2 = strtol(argv[7], NULL, 0);
+ br_sja1000->sam = strtol(argv[8], NULL, 0);
+
+ } else if (!strcmp(argv[3], "btr_c_can")) {
+ struct can_baudrate_c_can *br_c_can = &br->btr.c_can;
+
+ if (argc < 8)
+ help();
+
+ br->baudrate = CAN_BAUD_BTR_C_CAN;
+ br_c_can->brp = strtol(argv[4], NULL, 0);
+ br_c_can->sjw = strtol(argv[5], NULL, 0);
+ br_c_can->tseg1 = strtol(argv[6], NULL, 0);
+ br_c_can->tseg2 = strtol(argv[7], NULL, 0);
+
+ } else if (!strcmp(argv[3], "btr_nios")) {
+ struct can_baudrate_nios *br_nios = &br->btr.nios;
+
+ if (argc < 7)
+ help();
+
+ br->baudrate = CAN_BAUD_BTR_NIOS;
+ br_nios->prescale = strtol(argv[4], NULL, 0);
+ br_nios->timea = strtol(argv[5], NULL, 0);
+ br_nios->timeb = strtol(argv[6], NULL, 0);
+
+ } else {
+ value = atoi(argv[3]);
+ baudrate = can_value_to_baud(value);
+ if ( baudrate == -1) {
+ fprintf(stderr, "invalid baudrate\n");
+ exit(EXIT_FAILURE);
+ }
+ br->baudrate = baudrate;
+ }
+
+ i = ioctl(s, SIOCSCANBAUDRATE, &ifr);
+ if (i < 0) {
+ perror("ioctl");
+ exit(EXIT_FAILURE);
+ }
+}
+
+
+void cmd_baudrate(int argc, char *argv[])
+{
+ if (argc >= 4) {
+ do_set_baudrate(argc, argv);
+ }
+ do_show_baudrate(argc, argv);
+
+ exit(EXIT_SUCCESS);
+}
+
+
+void cmd_mode(int argc, char *argv[])
+{
+ union can_settings *settings = (union can_settings *)&ifr.ifr_ifru;
+ int i;
+
+ if (argc < 4 )
+ help();
+
+ if (!strcmp(argv[3], "start")) {
+ settings->mode = CAN_MODE_START;
+ } else {
+ help();
+ }
+
+ i = ioctl(s, SIOCSCANMODE, &ifr);
+ if (i < 0) {
+ perror("ioctl");
+ exit(EXIT_FAILURE);
+ }
+
+ exit(EXIT_SUCCESS);
+}
+
+
+void do_show_state(int argc, char *argv[])
+{
+ union can_settings *settings = (union can_settings *)&ifr.ifr_ifru;
+ enum CAN_STATE state;
+ char *str;
+ int i;
+
+ i = ioctl(s, SIOCGCANSTATE, &ifr);
+ if (i < 0) {
+ perror("ioctl");
+ exit(EXIT_FAILURE);
+ }
+
+ state = settings->state;
+ fprintf(stdout, "%s: state ", ifr.ifr_name);
+ switch (state) {
+ case CAN_STATE_BUS_PASSIVE:
+ str = "bus passive";
+ break;
+ case CAN_STATE_ACTIVE:
+ str = "active";
+ break;
+ case CAN_STATE_BUS_OFF:
+ str = "bus off";
+ break;
+ default:
+ str = "<unknown>";
+ }
+ fprintf(stdout, "%s \n", str);
+
+ exit(EXIT_SUCCESS);
+}
+
+
+void cmd_state(int argc, char *argv[])
+{
+ do_show_state(argc, argv);
+
+ exit(EXIT_SUCCESS);
+}
+
+
+void cmd_show_interface(int argc, char *argv[])
+{
+ do_show_baudrate(argc, argv);
+ do_show_state(argc, argv);
+
+ exit(EXIT_SUCCESS);
+}
+
+
+int main(int argc, char *argv[])
+{
+ if ((argc < 2) || !strcmp(argv[1], "--help"))
+ help();
+
+ if ((s = socket(AF_CAN, SOCK_RAW, 0)) < 0) {
+ perror("socket");
+ exit(EXIT_FAILURE);
+ }
+
+ strncpy(ifr.ifr_name, argv[1], IFNAMSIZ);
+
+ if (argc < 3)
+ cmd_show_interface(argc, argv);
+
+ if (!strcmp(argv[2], "baudrate"))
+ cmd_baudrate(argc, argv);
+ if (!strcmp(argv[2], "mode"))
+ cmd_mode(argc, argv);
+ if (!strcmp(argv[2], "state"))
+ cmd_state(argc, argv);
+
+ help();
+
+ return 0;
+}
diff --git a/src/candump.c b/src/candump.c
new file mode 100644
index 0000000..bf1514a
--- /dev/null
+++ b/src/candump.c
@@ -0,0 +1,187 @@
+#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,
+ FILTER_OPTION,
+};
+
+static void print_usage(char *prg)
+{
+ fprintf(stderr, "Usage: %s <can-interface> [Options]\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"
+ " --filter=id:mask[:id:mask]...\n"
+ " apply filter\n"
+ " -h, --help this help\n"
+ " --version print version information and exit\n",
+ prg, PF_CAN, SOCK_RAW, CAN_PROTO_RAW);
+}
+
+static void sigterm(int signo)
+{
+ running = 0;
+}
+
+static struct can_filter *filter = NULL;
+static int filter_count = 0;
+
+int add_filter(u_int32_t id, u_int32_t mask)
+{
+ filter = realloc(filter, sizeof(struct can_filter) * (filter_count + 1));
+ if(!filter)
+ return -1;
+
+ filter[filter_count].can_id = id;
+ filter[filter_count].can_mask = mask;
+ filter_count++;
+
+ printf("id: 0x%08x mask: 0x%08x\n",id,mask);
+ return 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, i;
+ struct ifreq ifr;
+ char *ptr;
+ u_int32_t id, mask;
+
+ 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' },
+ { "filter", required_argument, 0, FILTER_OPTION },
+ { "version", no_argument, 0, VERSION_OPTION},
+ { 0, 0, 0, 0},
+ };
+
+ while ((opt = getopt_long(argc, argv, "f:t:p:", 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 FILTER_OPTION:
+ ptr = optarg;
+ while(1) {
+ id = strtoul(ptr, NULL, 0);
+ ptr = strchr(ptr, ':');
+ if(!ptr) {
+ fprintf(stderr, "filter must be applied in the form id:mask[:id:mask]...\n");
+ exit(1);
+ }
+ ptr++;
+ mask = strtoul(ptr, NULL, 0);
+ ptr = strchr(ptr, ':');
+ add_filter(id,mask);
+ if(!ptr)
+ break;
+ ptr++;
+ }
+ break;
+
+ case VERSION_OPTION:
+ printf("candump %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(filter) {
+ if(setsockopt(s, SOL_CAN_RAW, SO_CAN_SET_FILTER, filter, filter_count * sizeof(struct can_filter)) != 0) {
+ perror("setsockopt");
+ exit(1);
+ }
+ }
+
+ while (running) {
+ if ((nbytes = read(s, &frame, sizeof(struct can_frame))) < 0) {
+ perror("read");
+ return 1;
+ } else {
+ if (frame.can_id & CAN_FLAG_EXTENDED)
+ printf("<0x%08x> ", frame.can_id & CAN_ID_EXT_MASK);
+ else
+ printf("<0x%03x> ", frame.can_id & CAN_ID_STD_MASK);
+
+ printf("[%d] ", frame.can_dlc);
+ for (i = 0; i < frame.can_dlc; i++) {
+ printf("%02x ", frame.payload.data_u8[i]);
+ }
+ if (frame.can_id & CAN_FLAG_RTR)
+ printf("remote request");
+ printf("\n");
+ }
+ }
+
+ exit (EXIT_SUCCESS);
+}
diff --git a/src/canecho.c b/src/canecho.c
new file mode 100644
index 0000000..a80b908
--- /dev/null
+++ b/src/canecho.c
@@ -0,0 +1,147 @@
+#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"
+ "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"
+ " -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)
+{
+ printf("got signal %d\n", 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, i;
+ int verbose = 0;
+ struct ifreq ifr;
+
+ 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},
+ { "verbose", no_argument, 0, 'v'},
+ { 0, 0, 0, 0},
+ };
+
+ while ((opt = getopt_long(argc, argv, "hf:t:p:v", long_options, NULL)) != -1) {
+ switch (opt) {
+ case 'f':
+ family = atoi(optarg);
+ break;
+
+ case 't':
+ type = atoi(optarg);
+ break;
+
+ case 'p':
+ proto = atoi(optarg);
+ break;
+
+ case 'v':
+ verbose = 1;
+ break;
+
+ case 'h':
+ print_usage(basename(argv[0]));
+ exit(0);
+
+ case VERSION_OPTION:
+ printf("canecho %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;
+ strcpy(ifr.ifr_name, argv[optind]);
+ 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;
+ }
+
+ while (running) {
+ if ((nbytes = read(s, &frame, sizeof(frame))) < 0) {
+ perror("read");
+ return 1;
+ }
+ if (verbose) {
+ printf("%04x: ", frame.can_id);
+ if (frame.can_id & CAN_FLAG_RTR) {
+ printf("remote request");
+ } else {
+ printf("[%d]", frame.can_dlc);
+ for (i = 0; i < frame.can_dlc; i++) {
+ printf(" %02x", frame.payload.data[i]);
+ }
+ }
+ printf("\n");
+ }
+ frame.can_id++;
+ write(s, &frame, sizeof(frame));
+ }
+
+ return 0;
+}
diff --git a/src/cansend.c b/src/cansend.c
new file mode 100644
index 0000000..80721c4
--- /dev/null
+++ b/src/cansend.c
@@ -0,0 +1,186 @@
+#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 <can_config.h>
+
+#include <socket-can/can.h>
+
+extern int optind, opterr, optopt;
+
+static void print_usage(char *prg)
+{
+ fprintf(stderr, "Usage: %s <can-interface> [Options] <can-msg>\n"
+ "<can-msg> can consist of up to 8 bytes given as a space separated list\n"
+ "Options:\n"
+ " -i, --identifier=ID CAN Identifier (default = 1)\n"
+ " -r --rtr send remote request\n"
+ " -e --extended send extended frame\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"
+ " -l send message infinite times\n"
+ " --loop=COUNT send message COUNT times\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);
+}
+
+enum
+{
+ VERSION_OPTION = CHAR_MAX + 1,
+};
+
+int main(int argc, char **argv)
+{
+ int family = PF_CAN, type = SOCK_RAW, proto = CAN_PROTO_RAW;
+ struct sockaddr_can addr;
+ int s, opt, ret, i, dlc = 0, rtr = 0, extended = 0;
+ struct can_frame frame;
+ int verbose = 0;
+ int loopcount = 1, infinite = 0;
+ struct ifreq ifr;
+
+ struct option long_options[] = {
+ { "help", no_argument, 0, 'h' },
+ { "identifier", required_argument, 0, 'i'},
+ { "rtr", no_argument, 0, 'r'},
+ { "extended", no_argument, 0, 'e'},
+ { "family", required_argument, 0, 'f' },
+ { "protocol", required_argument, 0, 'p' },
+ { "type", required_argument, 0, 't' },
+ { "version", no_argument, 0, VERSION_OPTION},
+ { "verbose", no_argument, 0, 'v'},
+ { "loop", required_argument, 0, 'l'},
+ { 0, 0, 0, 0},
+ };
+
+ frame.can_id = 1;
+
+ while ((opt = getopt_long(argc, argv, "hf:t:p:vi:lre", 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 'v':
+ verbose = 1;
+ break;
+
+ case 'l':
+ if(optarg)
+ loopcount = strtoul(optarg, NULL, 0);
+ else
+ infinite = 1;
+ break;
+ case 'i':
+ frame.can_id = strtoul(optarg, NULL, 0);
+ break;
+
+ case 'r':
+ rtr = 1;
+ break;
+
+ case 'e':
+ extended = 1;
+ break;
+
+ case VERSION_OPTION:
+ printf("cansend %s\n",VERSION);
+ exit(0);
+
+ default:
+ fprintf(stderr, "Unknown option %c\n", opt);
+ break;
+ }
+ }
+
+ if (optind == argc) {
+ print_usage(basename(argv[0]));
+ exit(0);
+ }
+
+ if (argv[optind] == NULL) {
+ fprintf(stderr, "No Interface supplied\n");
+ exit(-1);
+ }
+
+ if(verbose)
+ 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;
+ strcpy(ifr.ifr_name, argv[optind]);
+ if( ioctl(s, SIOCGIFINDEX, &ifr) ) {
+ perror("ioctl");
+ return 1;
+ }
+ addr.can_ifindex = ifr.ifr_ifindex;
+ addr.can_id = frame.can_id;
+
+ if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ perror("bind");
+ return 1;
+ }
+
+
+ for(i = optind + 1; i < argc; i++) {
+ frame.payload.data[dlc] = strtoul(argv[i], NULL, 0);
+ dlc++;
+ if( dlc == 8 )
+ break;
+ }
+ frame.can_dlc = dlc;
+
+ if(rtr)
+ frame.can_id |= CAN_FLAG_RTR;
+
+ if(extended)
+ frame.can_id |= CAN_FLAG_EXTENDED;
+
+ if(verbose) {
+ printf("id: %d ",frame.can_id);
+ printf("dlc: %d\n",frame.can_dlc);
+ for(i = 0; i < frame.can_dlc; i++)
+ printf("0x%02x ",frame.payload.data[i]);
+ printf("\n");
+ }
+
+ while (infinite || loopcount--) {
+ ret = write(s, &frame, sizeof(frame));
+ if( ret == -1 ) {
+ perror("write");
+ break;
+ }
+ }
+
+ close(s);
+ return 0;
+}
diff --git a/src/cansequence.c b/src/cansequence.c
new file mode 100644
index 0000000..e569b1b
--- /dev/null
+++ b/src/cansequence.c
@@ -0,0 +1,195 @@
+#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 (twice to be even more 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++;
+ 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_u8[0];
+ }
+ if(verbose>1)
+ printf("received frame. sequence number: %d\n",sequence);
+ if( frame.payload.data_u8[0] != sequence) {
+ printf("received wrong sequence count. expected: %d, got: %d\n",
+ frame.payload.data_u8[0], sequence);
+ if(quit)
+ exit(1);
+ sequence = frame.payload.data_u8[0];
+ }
+ if(verbose && !sequence)
+ printf("sequence wrap around\n");
+ sequence++;
+ }
+ }
+ } else {
+ frame.can_dlc = 1;
+ frame.can_id = 2;
+ frame.payload.data[0] = 0;
+ while ((infinite || loopcount--) && running) {
+ if(verbose>1)
+ printf("sending frame. sequence number: %d\n",sequence);
+ if(verbose && !sequence)
+ printf("sequence wrap around\n");
+ if( write(s, &frame, sizeof(frame)) < 0) {
+ perror("write");
+ break;
+ }
+ (unsigned char)frame.payload.data[0]++;
+ sequence++;
+ }
+ }
+ return 0;
+}