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