diff options
author | Marc Kleine-Budde <mkl@pengutronix.de> | 2005-11-29 13:32:13 +0000 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2005-11-29 13:32:13 +0000 |
commit | e7c603844d1a3af80f2d2aaac3c9c8e3674bccfe (patch) | |
tree | fe346bf498779fcb891cfa15b2cc86777e85d03c /src | |
parent | 6c317b329562fe898737fe3c7b516922e2f075f4 (diff) | |
download | canutils-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.am | 15 | ||||
-rw-r--r-- | src/canconfig.c | 328 | ||||
-rw-r--r-- | src/candump.c | 187 | ||||
-rw-r--r-- | src/canecho.c | 147 | ||||
-rw-r--r-- | src/cansend.c | 186 | ||||
-rw-r--r-- | src/cansequence.c | 195 |
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; +} |