Hi,

I'd like to introduce cancat, a netcat like utility for the CAN Bus.

How does it work:

Everything read from standard input will be written to the CAN Bus,
everything read from the CAN Bus will be written to standard output.
There is no conversion {from, to} ASCII involved.
Currently the first "can0" interface will be used.


How to apply the patch and build cancat:

(tested against socketcan-trunk r1120)

(save patch to some empty temporary directory and execute
the following shell script)

#!/bin/sh
svn checkout svn://svn.berlios.de/socketcan/trunk
cd trunk
patch -p1 < ../cancat.diff
cd can-utils
make


diff --git a/can-utils/Makefile b/can-utils/Makefile
index 91dfc04..848f9f2 100644
--- a/can-utils/Makefile
+++ b/can-utils/Makefile
@@ -53,7 +53,7 @@ CFLAGS    = -O2 -Wall -Wno-parentheses -I$(KERNELDIR)/include \
 PROGRAMS = candump cansniffer cansend canplayer canlogserver cangen\
 	   canbusload log2long log2asc asc2log bcmserver\
 	   isotpdump isotprecv isotpsend isotpsniffer isotptun\
-	   slcan_attach slcand slcanpty canfdtest
+	   slcan_attach slcand slcanpty canfdtest cancat
 
 all: $(PROGRAMS)
 
@@ -84,3 +84,4 @@ canlogserver:	canlogserver.o	lib.o
 log2long:	log2long.o	lib.o
 log2asc:	log2asc.o	lib.o
 asc2log:	asc2log.o	lib.o
+cancat: 	cancat.o
diff --git a/can-utils/cancat.c b/can-utils/cancat.c
new file mode 100644
index 0000000..9d2e68a
--- /dev/null
+++ b/can-utils/cancat.c
@@ -0,0 +1,112 @@
+/* 
+ * Copyright (c) 2009,2010 Michael Burian
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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, see <http://www.gnu.org/licenses/>.
+ *
+ * --------------------------------------------------------------------
+ * cancat.c 
+ * 
+ * A netcat-like utility for the CAN bus
+ * 
+ * Read can_frames from standard input and write them to the CAN bus,
+ * read can_frames from the CAN bus and write them to standard output.
+ *
+ * Note: We are processing binary "struct can_frame" data here.
+ * This is not to be confused with the ASCII based format that
+ * some other socketcan utils use.
+ *
+ * Usage examples:
+ * 
+ * # 1. send can_frames from file to CAN bus 
+ * cancat < file_containing_can_frames_to_send
+ * 
+ * # 2. read can_frames from the CAN bus and write them into a file
+ * cancat > can_frames.log
+ * 
+ * # 3. read and write
+ * # can_frames written by "some_unix_filter_prog" to standard output
+ * # are sent to the CAN bus, while anything read from the CAN bus
+ * # is passed to "some_unix_filter_prog" via standard input
+ * socat SYSTEM:"cancat" SYSTEM:"some_unix_filter_prog"
+ */
+
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+
+#include <linux/can.h>
+#include <linux/can/raw.h>
+#include <poll.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+/* TODO: un-hardcode "can0" and pass as command line argument instead */
+
+int main(int argc, char **argv)
+{
+	/* Create the socket */
+	int skt = socket(PF_CAN, SOCK_RAW, CAN_RAW);
+
+	/* Locate the interface you wish to use */
+	struct ifreq ifr = { {{0}} };
+	memcpy(ifr.ifr_name, "can0", sizeof("can0"));
+	ioctl(skt, SIOCGIFINDEX, &ifr);	/* ifr.ifr_ifindex gets filled 
+					 * with that device's index */
+
+	/* Select that CAN interface, and bind the socket to it. */
+	struct sockaddr_can addr = { 0 };
+	addr.can_family = AF_CAN;
+	addr.can_ifindex = ifr.ifr_ifindex;
+	bind(skt, (struct sockaddr *)&addr, sizeof(addr));
+
+	/* Send a message to the CAN bus */
+	struct can_frame frame;
+
+	struct pollfd pollfd_list[2];
+	pollfd_list[0].fd = STDIN_FILENO;
+	pollfd_list[0].events = POLLIN | POLLPRI;
+	pollfd_list[1].fd = skt;
+	pollfd_list[1].events = POLLIN | POLLPRI;
+
+	const int CLEN = sizeof(struct can_frame);
+
+	while (1) {
+		if (-1 == poll(pollfd_list, 2, -1)) {
+			perror("Poll error");
+		}
+		// something to read from STDIN: write to CAN
+		if (pollfd_list[0].revents & (POLLIN | POLLPRI)) {
+			if (CLEN != read(STDIN_FILENO, &frame, CLEN)) {
+				fprintf(stderr, "STDIN read error, discarding frame\n");
+			} else {
+				// read successful, so try write
+				if (CLEN != write(skt, &frame, CLEN)) {
+					fprintf(stderr, "CAN write error\n");
+				}
+			}
+		}
+		// something to read from CAN: write to STDOUT
+		if (pollfd_list[1].revents & (POLLIN | POLLPRI)) {
+			if (CLEN != read(skt, &frame, CLEN)) {
+				fprintf(stderr, "CAN read error, discarding frame\n");
+			} else {
+				if (CLEN != write(STDOUT_FILENO, &frame, CLEN)) {
+					fprintf(stderr, "STDOUT write error\n");
+				}
+			}
+		}
+	}
+}
+
_______________________________________________
Socketcan-core mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/socketcan-core

Reply via email to