From e7c603844d1a3af80f2d2aaac3c9c8e3674bccfe Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Tue, 29 Nov 2005 13:32:13 +0000 Subject: * code restructured git-svn-id: https://iocaste.extern.pengutronix.de/svn/canutils/trunks/canutils-1.0-trunk@54 5fd5a299-6ef2-0310-aa18-8b01d7c39d8c --- GNUmakefile.am | 23 ++++ INSTALL | 42 ------- Makefile.am | 37 ------ NEWS | 0 README | 0 autogen.sh | 47 +++++-- canconfig.8 | 61 --------- canconfig.c | 328 ------------------------------------------------- candump.8 | 35 ------ candump.c | 187 ---------------------------- canecho.8 | 41 ------- canecho.c | 147 ---------------------- cansend.8 | 38 ------ cansend.c | 186 ---------------------------- cansequence.c | 195 ----------------------------- config/GNUmakefile.am | 7 ++ config/Makefile.am | 7 -- configure.ac | 57 +++++++-- include/GNUmakefile.am | 6 + include/Makefile.am | 6 - man/GNUmakefile.am | 8 ++ man/canconfig.8 | 61 +++++++++ man/candump.8 | 35 ++++++ man/canecho.8 | 41 +++++++ man/cansend.8 | 38 ++++++ src/GNUmakefile.am | 15 +++ src/canconfig.c | 328 +++++++++++++++++++++++++++++++++++++++++++++++++ src/candump.c | 187 ++++++++++++++++++++++++++++ src/canecho.c | 147 ++++++++++++++++++++++ src/cansend.c | 186 ++++++++++++++++++++++++++++ src/cansequence.c | 195 +++++++++++++++++++++++++++++ 31 files changed, 1365 insertions(+), 1326 deletions(-) create mode 100644 GNUmakefile.am delete mode 100644 INSTALL delete mode 100644 Makefile.am delete mode 100644 NEWS delete mode 100644 README delete mode 100644 canconfig.8 delete mode 100644 canconfig.c delete mode 100644 candump.8 delete mode 100644 candump.c delete mode 100644 canecho.8 delete mode 100644 canecho.c delete mode 100644 cansend.8 delete mode 100644 cansend.c delete mode 100644 cansequence.c create mode 100644 config/GNUmakefile.am delete mode 100644 config/Makefile.am create mode 100644 include/GNUmakefile.am delete mode 100644 include/Makefile.am create mode 100644 man/GNUmakefile.am create mode 100644 man/canconfig.8 create mode 100644 man/candump.8 create mode 100644 man/canecho.8 create mode 100644 man/cansend.8 create mode 100644 src/GNUmakefile.am create mode 100644 src/canconfig.c create mode 100644 src/candump.c create mode 100644 src/canecho.c create mode 100644 src/cansend.c create mode 100644 src/cansequence.c diff --git a/GNUmakefile.am b/GNUmakefile.am new file mode 100644 index 0000000..30a7a20 --- /dev/null +++ b/GNUmakefile.am @@ -0,0 +1,23 @@ +SUBDIRS = include config src + +EXTRA_DIST = \ + autogen.sh \ + config/m4/.secret-world-domination-project + +MAINTAINERCLEANFILES = \ + configure \ + GNUmakefile.in \ + aclocal.m4 \ + config/autoconf/compile \ + config/autoconf/config.guess \ + config/autoconf/config.sub \ + config/autoconf/depcomp \ + config/autoconf/install-sh \ + config/autoconf/ltmain.sh \ + config/autoconf/mdate-sh \ + config/autoconf/missing \ + config/autoconf/texinfo.tex \ + config/m4/libtool.m4 \ + config/m4/ltoptions.m4 \ + config/m4/ltsugar.m4 \ + config/m4/ltversion.m4 diff --git a/INSTALL b/INSTALL deleted file mode 100644 index b8e3542..0000000 --- a/INSTALL +++ /dev/null @@ -1,42 +0,0 @@ -Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software -Foundation, Inc. - - This file is free documentation; the Free Software Foundation gives -unlimited permission to copy, distribute and modify it. - -canutils Installation -===================== - -To install canutils the usual autotools triple can be used: - - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. - - Running `configure' takes awhile. While running, it prints some - messages telling which features it is checking for. - - 2. Type `make' to compile the package. - - 3. Optionally, type `make check' to run any self-tests that come with - the package. - - 4. Type `make install' to install the programs and any data files and - documentation. - - 5. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. - -For further options of the configure script please have a look at the -output of 'configure --help' or read the autotools manual. - -Optional Features -================= - -canutils have no optional features at the moment. - diff --git a/Makefile.am b/Makefile.am deleted file mode 100644 index ced7bc3..0000000 --- a/Makefile.am +++ /dev/null @@ -1,37 +0,0 @@ -bin_PROGRAMS = candump canecho cansend cansequence -sbin_PROGRAMS = canconfig - -SUBDIRS = include config - -AM_CPPFLAGS = \ - -I$(top_srcdir)/include - -I$(top_builddir)/include - -candump_SOURCES = candump.c -canecho_SOURCES = canecho.c -cansend_SOURCES = cansend.c -canconfig_SOURCES = canconfig.c -cansequence_SOURCES = cansequence.c - -EXTRA_DIST = \ - autogen.sh \ - config/m4/.secret-world-domination-project \ - \ - canconfig.8 \ - candump.8 \ - canecho.8 \ - cansend.8 - -man_MANS = canconfig.8 candump.8 canecho.8 cansend.8 - -MAINTAINERCLEANFILES = \ - configure \ - Makefile.in \ - aclocal.m4 \ - config/autoconf/depcomp \ - config/autoconf/missing \ - config/autoconf/config.guess \ - config/autoconf/config.sub \ - config/autoconf/ltmain.sh \ - config/autoconf/install-sh - diff --git a/NEWS b/NEWS deleted file mode 100644 index e69de29..0000000 diff --git a/README b/README deleted file mode 100644 index e69de29..0000000 diff --git a/autogen.sh b/autogen.sh index 3bcd1a7..76a7de0 100644 --- a/autogen.sh +++ b/autogen.sh @@ -1,14 +1,27 @@ #!/bin/sh + +# +# usage: +# +# banner +# +banner() { + + echo + TG=`echo $1 | sed -e "s,/.*/,,g"` + LINE=`echo $TG |sed -e "s/./-/g"` + echo $LINE + echo $TG + echo $LINE + echo +} + + ACLOCAL=${ACLOCAL:=aclocal} AUTOHEADER=${AUTOHEADER:=autoheader} AUTOMAKE=${AUTOMAKE:=automake} AUTOCONF=${AUTOCONF:=autoconf} -echo use aclocal: $ACLOCAL -echo use autoheader: $AUTOHEADER -echo use automake: $AUTOMAKE -echo use autoconf: $AUTOCONF - $ACLOCAL --version | \ awk -vPROG="aclocal" -vVERS=1.7\ '{if ($1 == PROG) {gsub ("-.*","",$4); if ($4 < VERS) print PROG" < version "VERS"\nThis may result in errors\n"}}' @@ -17,9 +30,25 @@ $AUTOMAKE --version | \ awk -vPROG="automake" -vVERS=1.7\ '{if ($1 == PROG) {gsub ("-.*","",$4); if ($4 < VERS) print PROG" < version "VERS"\nThis may result in errors\n"}}' -$ACLOCAL -I config/m4 && \ -libtoolize --force && \ -$AUTOHEADER && \ -$AUTOMAKE --gnu --add-missing -Wall && \ + +banner "running libtoolize" +libtoolize --force +[ $? != 0 ] && exit + +banner "running aclocal" +$ACLOCAL -I config/m4 +[ $? != 0 ] && exit + +banner "running autoheader" +$AUTOHEADER +[ $? != 0 ] && exit + +banner "running automake" +$AUTOMAKE --gnu --add-missing -Wall +[ $? != 0 ] && exit + +banner "running autoconf" $AUTOCONF -Wall +[ $? != 0 ] && exit +banner "Finished" diff --git a/canconfig.8 b/canconfig.8 deleted file mode 100644 index c02247a..0000000 --- a/canconfig.8 +++ /dev/null @@ -1,61 +0,0 @@ -.TH CANCONFIG 8 "13 March 2005" "canutils" "Linux Programmer's Manual" -.SH NAME -canconfig \- configure a CAN bus interface -.SH SYNOPSIS -.B "canconfig " -.br -.B "canconfig baudrate { BR | BTR }" -.br -.B "canconfig mode MODE" -.br -.B "canconfig state" -.SH DESCRIPTION -canconfig is used to configure the kernel-resident CAN (Controller Area Network) -interfaces. As CAN cards are network devices the basic configuration -options can be done with ifconfig. - -.SH ARGUMENTS -.TP -.B interface -The name of the interface. This is usually a driver name followed by -a unit number, for example "can0". -.TP -.B baudrate -The baudrate of the CAN interface can be set with a simple and complex -method, which are chosen by using BR or BTR with the "baudrate" command. -.br - -.B BR: -The baudrate of the interface can be set to one of the standard baud -rates by setting a BR value. Example: - - canconfig can0 baudrate 125 - -to set the interface can0 to 125 kBit/s. The standard baudrates are 10, -20, 50, 100, 125, 250, 500, 800 and 1000 kBit/s. -.br - -.B BTR: -The CAN standard defines a second way for setting the baudrate, which -uses a set of Bit Timing Registers (BTR). The number of and exact -meaning of the BTR registers is chip dependend, so this interface offers -the possibility to handle three BTR registers directly to the driver: - - canconfig can0 baudrate btr - -.TP -.B mode -This command sets the CAN controller into "start" mode. Example: - - canconfig can0 mode start - -.TP -.B state -This command lets you ask for the interface status. -.br -.SH SEE ALSO -- ifconfig(8) -.br -- http://www.pengutronix.de/software/socket-can/ (Socket-CAN Project) -.SH AUTHORS -Robert Schwebel diff --git a/canconfig.c b/canconfig.c deleted file mode 100644 index 9207fe5..0000000 --- a/canconfig.c +++ /dev/null @@ -1,328 +0,0 @@ -/* - * canutils/canconfig.c - * - * Copyright (C) 2005 Marc Kleine-Budde , 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 -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include - -#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 baudrate { BR | BTR }\n\t\t" - "BR := { 10 | 20 | 50 | 100 | 125 | 250 | 500 | 800 | 1000 }\n\t\t" - "BTR := btr_sja1000 \n\t\t" - "BTR := btr_c_can \n\t\t" - "BTR := btr_nios \n\t" - "canconfig mode MODE\n\t\t" - "MODE := { start }\n\t" - "canconfig 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 = ""; - } - 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/candump.8 b/candump.8 deleted file mode 100644 index cd11f89..0000000 --- a/candump.8 +++ /dev/null @@ -1,35 +0,0 @@ -.TH CANDUMP 8 "13 March 2005" "canutils" "Linux Programmer's Manual" -.SH NAME -candump \- dump messages from CAN bus interfaces to stdout -.SH SYNOPSIS -.B "candump [Options]" -.br -.SH DESCRIPTION -candump receives messages from a CAN (Controller Area Network) bus -interface and dumps it to stdout. - -.SH ARGUMENTS and OPTIONS -.TP -.B interface -The name of the interface. This is usually a driver name followed by -a unit number, for example "can0". -.TP -.B -f family -Specifies the protocol family which has to be sniffed for. Default is -PF_CAN, which is 30. -.TP -.B -t type -Specifies the socket type to be sniffed on. Default is SOCK_RAW, which -is 3. -.TP -.B -p proto -Specifies the protocol to sniff for; default is CAN_PROTO_RAW, which is -0. -.br -.SH SEE ALSO -- ifconfig(8), canconfig(8), canecho(8) -.br -- http://www.pengutronix.de/software/socket-can/ (Socket-CAN Project) -.SH AUTHORS -Marc Kleine-Budde -Robert Schwebel diff --git a/candump.c b/candump.c deleted file mode 100644 index bf1514a..0000000 --- a/candump.c +++ /dev/null @@ -1,187 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -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 [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/canecho.8 b/canecho.8 deleted file mode 100644 index f453ac6..0000000 --- a/canecho.8 +++ /dev/null @@ -1,41 +0,0 @@ -.TH CANECHO 8 "13 March 2005" "canutils" "Linux Programmer's Manual" -.SH NAME -canecho \- loop back received CAN messages to the interface -.SH SYNOPSIS -.B "canecho [Options]" -.br -.SH DESCRIPTION -canecho receives messages from a CAN (Controller Area Network) bus -interface and directly sends the message back to the same interface. -This can be used to test a remote CAN node by sending messages and -testing if the same messages are being echoed back. - -.SH ARGUMENTS and OPTIONS -.TP -.B interface -The name of the interface. This is usually a driver name followed by -a unit number, for example "can0". -.TP -.B -f family -Specifies the protocol family which has to be sniffed for. Default is -PF_CAN, which is 30. -.TP -.B -t type -Specifies the socket type to be sniffed on. Default is SOCK_RAW, which -is 3. -.TP -.B -p proto -Specifies the protocol to sniff for; default is CAN_PROTO_RAW, which -is 0. -.TP -.B -v -Verbose mode. -0. -.br -.SH SEE ALSO -- ifconfig(8), canconfig(8), candump(8), cansend(8) -.br -- http://www.pengutronix.de/software/socket-can/ (Socket-CAN Project) -.SH AUTHORS -Marc Kleine-Budde -Robert Schwebel diff --git a/canecho.c b/canecho.c deleted file mode 100644 index a80b908..0000000 --- a/canecho.c +++ /dev/null @@ -1,147 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -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 [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/cansend.8 b/cansend.8 deleted file mode 100644 index 66f96bd..0000000 --- a/cansend.8 +++ /dev/null @@ -1,38 +0,0 @@ -.TH CANSEND 8 "13 March 2005" "canutils" "Linux Programmer's Manual" -.SH NAME -cansend \- send data on a CAN interface -.SH SYNOPSIS -.B "send [Options] -i message" -.br -.SH DESCRIPTION -cansend sends messages on a CAN (Controller Area Network) bus interface. - -.SH ARGUMENTS and OPTIONS -.TP -.B interface -The name of the interface. This is usually a driver name followed by -a unit number, for example "can0". -.TP -.B -f family -Specifies the protocol family which has to be sniffed for. Default is -PF_CAN, which is 30. -.TP -.B -t type -Specifies the socket type to be sniffed on. Default is SOCK_RAW, which -is 3. -.TP -.B -p proto -Specifies the protocol to sniff for; default is CAN_PROTO_RAW, which -is 0. -.TP -.B -v -Verbose mode. -0. -.br -.SH SEE ALSO -- ifconfig(8), canconfig(8), candump(8), cansend(8) -.br -- http://www.pengutronix.de/software/socket-can/ (Socket-CAN Project) -.SH AUTHORS -Marc Kleine-Budde -Robert Schwebel diff --git a/cansend.c b/cansend.c deleted file mode 100644 index 80721c4..0000000 --- a/cansend.c +++ /dev/null @@ -1,186 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include - -extern int optind, opterr, optopt; - -static void print_usage(char *prg) -{ - fprintf(stderr, "Usage: %s [Options] \n" - " 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/cansequence.c b/cansequence.c deleted file mode 100644 index e569b1b..0000000 --- a/cansequence.c +++ /dev/null @@ -1,195 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -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 [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; -} diff --git a/config/GNUmakefile.am b/config/GNUmakefile.am new file mode 100644 index 0000000..b77daeb --- /dev/null +++ b/config/GNUmakefile.am @@ -0,0 +1,7 @@ +EXTRA_DIST = canutils.pc.in + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = canutils.pc + +MAINTAINERCLEANFILES = \ + GNUmakefile.in diff --git a/config/Makefile.am b/config/Makefile.am deleted file mode 100644 index e373214..0000000 --- a/config/Makefile.am +++ /dev/null @@ -1,7 +0,0 @@ -EXTRA_DIST = canutils.pc.in - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = canutils.pc - -MAINTAINERCLEANFILES = \ - Makefile.in \ No newline at end of file diff --git a/configure.ac b/configure.ac index 2658842..b1328e9 100644 --- a/configure.ac +++ b/configure.ac @@ -2,9 +2,9 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.59) -AC_INIT([canutils], [1.0.5], [socket-can@pengutronix.de]) +AC_INIT([canutils], [1.0.6], [socket-can@pengutronix.de]) AC_CONFIG_HEADERS([include/can_config.h]) -AC_CONFIG_SRCDIR([cansend.c]) +AC_CONFIG_SRCDIR([src/canconfig.c]) AC_CONFIG_MACRO_DIR([config/m4]) AC_CONFIG_AUX_DIR([config/autoconf]) AC_CANONICAL_BUILD @@ -12,16 +12,29 @@ AC_CANONICAL_HOST CFLAGS="${CFLAGS} -Wall -O2 -g" +# # Checks for programs. +# AC_PROG_CC -AC_PROG_INSTALL +AM_MISSING_PROG(PERL, perl, $missing_dir) +# libtool, old: +AC_LIBTOOL_WIN32_DLL +#AC_LIBTOOL_TAGS([]) AC_PROG_LIBTOOL +# libtool, new: +# LT_INIT(win32-dll) AM_INIT_AUTOMAKE([foreign no-exeext dist-bzip2]) + +# # Checks for libraries. +# + +# # Checks for header files. +# AC_HEADER_STDC AC_CHECK_HEADERS([ \ fcntl.h \ @@ -37,15 +50,45 @@ AC_CHECK_HEADERS([ \ sys/socket.h \ ]) +# # Checks for typedefs, structures, and compiler characteristics. +# +AC_C_CONST +AC_C_INLINE AC_TYPE_SIZE_T +AC_HEADER_TIME + +# # Checks for library functions. +# + + +# +# Debugging +# +AC_MSG_CHECKING([whether to enable debugging]) +AC_ARG_ENABLE(debug, + AS_HELP_STRING([--enable-debug], [enable debugging @<:@default=no@:>@]), + [case "$enableval" in + y | yes) CONFIG_DEBUG=yes ;; + *) CONFIG_DEBUG=no ;; + esac], + [CONFIG_DEBUG=no]) +AC_MSG_RESULT([${CONFIG_DEBUG}]) +if test "${CONFIG_DEBUG}" = "yes"; then + CFLAGS="${CFLAGS} -Werror -g -O1" + AC_DEFINE(DEBUG, 1, [debugging]) +else + CFLAGS="${CFLAGS} -O2" +fi + + AC_CONFIG_FILES([ \ - Makefile \ + GNUmakefile \ config/canutils.pc \ - config/Makefile \ - include/Makefile \ + config/GNUmakefile \ + include/GNUmakefile \ + src/GNUmakefile ]) - AC_OUTPUT diff --git a/include/GNUmakefile.am b/include/GNUmakefile.am new file mode 100644 index 0000000..e398444 --- /dev/null +++ b/include/GNUmakefile.am @@ -0,0 +1,6 @@ +nobase_include_HEADERS = socket-can/can.h + +MAINTAINERCLEANFILES = \ + can_config.h.in \ + GNUmakefile.in + diff --git a/include/Makefile.am b/include/Makefile.am deleted file mode 100644 index 14df547..0000000 --- a/include/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -nobase_include_HEADERS = socket-can/can.h - -MAINTAINERCLEANFILES= \ - can_config.h.in \ - Makefile.in - diff --git a/man/GNUmakefile.am b/man/GNUmakefile.am new file mode 100644 index 0000000..7fd6fb2 --- /dev/null +++ b/man/GNUmakefile.am @@ -0,0 +1,8 @@ +man_MANS = \ + canconfig.8 \ + candump.8 \ + canecho.8 \ + cansend.8 + +MAINTAINERCLEANFILES = \ + GNUmakefile.in diff --git a/man/canconfig.8 b/man/canconfig.8 new file mode 100644 index 0000000..c02247a --- /dev/null +++ b/man/canconfig.8 @@ -0,0 +1,61 @@ +.TH CANCONFIG 8 "13 March 2005" "canutils" "Linux Programmer's Manual" +.SH NAME +canconfig \- configure a CAN bus interface +.SH SYNOPSIS +.B "canconfig " +.br +.B "canconfig baudrate { BR | BTR }" +.br +.B "canconfig mode MODE" +.br +.B "canconfig state" +.SH DESCRIPTION +canconfig is used to configure the kernel-resident CAN (Controller Area Network) +interfaces. As CAN cards are network devices the basic configuration +options can be done with ifconfig. + +.SH ARGUMENTS +.TP +.B interface +The name of the interface. This is usually a driver name followed by +a unit number, for example "can0". +.TP +.B baudrate +The baudrate of the CAN interface can be set with a simple and complex +method, which are chosen by using BR or BTR with the "baudrate" command. +.br + +.B BR: +The baudrate of the interface can be set to one of the standard baud +rates by setting a BR value. Example: + + canconfig can0 baudrate 125 + +to set the interface can0 to 125 kBit/s. The standard baudrates are 10, +20, 50, 100, 125, 250, 500, 800 and 1000 kBit/s. +.br + +.B BTR: +The CAN standard defines a second way for setting the baudrate, which +uses a set of Bit Timing Registers (BTR). The number of and exact +meaning of the BTR registers is chip dependend, so this interface offers +the possibility to handle three BTR registers directly to the driver: + + canconfig can0 baudrate btr + +.TP +.B mode +This command sets the CAN controller into "start" mode. Example: + + canconfig can0 mode start + +.TP +.B state +This command lets you ask for the interface status. +.br +.SH SEE ALSO +- ifconfig(8) +.br +- http://www.pengutronix.de/software/socket-can/ (Socket-CAN Project) +.SH AUTHORS +Robert Schwebel diff --git a/man/candump.8 b/man/candump.8 new file mode 100644 index 0000000..cd11f89 --- /dev/null +++ b/man/candump.8 @@ -0,0 +1,35 @@ +.TH CANDUMP 8 "13 March 2005" "canutils" "Linux Programmer's Manual" +.SH NAME +candump \- dump messages from CAN bus interfaces to stdout +.SH SYNOPSIS +.B "candump [Options]" +.br +.SH DESCRIPTION +candump receives messages from a CAN (Controller Area Network) bus +interface and dumps it to stdout. + +.SH ARGUMENTS and OPTIONS +.TP +.B interface +The name of the interface. This is usually a driver name followed by +a unit number, for example "can0". +.TP +.B -f family +Specifies the protocol family which has to be sniffed for. Default is +PF_CAN, which is 30. +.TP +.B -t type +Specifies the socket type to be sniffed on. Default is SOCK_RAW, which +is 3. +.TP +.B -p proto +Specifies the protocol to sniff for; default is CAN_PROTO_RAW, which is +0. +.br +.SH SEE ALSO +- ifconfig(8), canconfig(8), canecho(8) +.br +- http://www.pengutronix.de/software/socket-can/ (Socket-CAN Project) +.SH AUTHORS +Marc Kleine-Budde +Robert Schwebel diff --git a/man/canecho.8 b/man/canecho.8 new file mode 100644 index 0000000..f453ac6 --- /dev/null +++ b/man/canecho.8 @@ -0,0 +1,41 @@ +.TH CANECHO 8 "13 March 2005" "canutils" "Linux Programmer's Manual" +.SH NAME +canecho \- loop back received CAN messages to the interface +.SH SYNOPSIS +.B "canecho [Options]" +.br +.SH DESCRIPTION +canecho receives messages from a CAN (Controller Area Network) bus +interface and directly sends the message back to the same interface. +This can be used to test a remote CAN node by sending messages and +testing if the same messages are being echoed back. + +.SH ARGUMENTS and OPTIONS +.TP +.B interface +The name of the interface. This is usually a driver name followed by +a unit number, for example "can0". +.TP +.B -f family +Specifies the protocol family which has to be sniffed for. Default is +PF_CAN, which is 30. +.TP +.B -t type +Specifies the socket type to be sniffed on. Default is SOCK_RAW, which +is 3. +.TP +.B -p proto +Specifies the protocol to sniff for; default is CAN_PROTO_RAW, which +is 0. +.TP +.B -v +Verbose mode. +0. +.br +.SH SEE ALSO +- ifconfig(8), canconfig(8), candump(8), cansend(8) +.br +- http://www.pengutronix.de/software/socket-can/ (Socket-CAN Project) +.SH AUTHORS +Marc Kleine-Budde +Robert Schwebel diff --git a/man/cansend.8 b/man/cansend.8 new file mode 100644 index 0000000..66f96bd --- /dev/null +++ b/man/cansend.8 @@ -0,0 +1,38 @@ +.TH CANSEND 8 "13 March 2005" "canutils" "Linux Programmer's Manual" +.SH NAME +cansend \- send data on a CAN interface +.SH SYNOPSIS +.B "send [Options] -i message" +.br +.SH DESCRIPTION +cansend sends messages on a CAN (Controller Area Network) bus interface. + +.SH ARGUMENTS and OPTIONS +.TP +.B interface +The name of the interface. This is usually a driver name followed by +a unit number, for example "can0". +.TP +.B -f family +Specifies the protocol family which has to be sniffed for. Default is +PF_CAN, which is 30. +.TP +.B -t type +Specifies the socket type to be sniffed on. Default is SOCK_RAW, which +is 3. +.TP +.B -p proto +Specifies the protocol to sniff for; default is CAN_PROTO_RAW, which +is 0. +.TP +.B -v +Verbose mode. +0. +.br +.SH SEE ALSO +- ifconfig(8), canconfig(8), candump(8), cansend(8) +.br +- http://www.pengutronix.de/software/socket-can/ (Socket-CAN Project) +.SH AUTHORS +Marc Kleine-Budde +Robert Schwebel 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 , 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#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 baudrate { BR | BTR }\n\t\t" + "BR := { 10 | 20 | 50 | 100 | 125 | 250 | 500 | 800 | 1000 }\n\t\t" + "BTR := btr_sja1000 \n\t\t" + "BTR := btr_c_can \n\t\t" + "BTR := btr_nios \n\t" + "canconfig mode MODE\n\t\t" + "MODE := { start }\n\t" + "canconfig 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 = ""; + } + 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +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 [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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +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 [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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include + +extern int optind, opterr, optopt; + +static void print_usage(char *prg) +{ + fprintf(stderr, "Usage: %s [Options] \n" + " 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +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 [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; +} -- cgit v1.2.3