--- /dev/null
+CFLAGS = -g -O2 -Wall
+
+SRCS = $(wildcard *.c)
+BINS = $(SRCS:%.c=%)
+
+all: $(BINS)
+
+%: %.c common.h
+ $(CC) $(CFLAGS) -o $@ $<
--- /dev/null
+/**************************************************************/
+/* CAN system calls example */
+/* Author: Michal Sojka, Czech Technical University in Prague */
+/* License: Public domain */
+/**************************************************************/
+
+#include "common.h"
+
+#include <linux/can.h>
+#include <net/if.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <linux/if_packet.h>
+#include <net/ethernet.h> /* the L2 protocols */
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <sys/mman.h>
+#include <poll.h>
+
+#define FRAME_SIZE 128
+#define BLOCK_SIZE 4096
+#define BLOCK_NR 2
+#define FRAME_NR (BLOCK_NR*(BLOCK_SIZE/FRAME_SIZE))
+
+void *rx_ring_buffer;
+int hdrlen;
+int current;
+
+int init_mmap_socket(const char *dev)
+{
+ int sock;
+ struct sockaddr_ll addr;
+ struct ifreq ifr;
+
+ sock = CHECK(socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)));
+
+ int val = TPACKET_V2;
+ CHECK(setsockopt(sock, SOL_PACKET, PACKET_VERSION, &val, sizeof(val)));
+ socklen_t len = sizeof(hdrlen);
+ CHECK(getsockopt(sock, SOL_PACKET, PACKET_HDRLEN, &hdrlen, &len));
+
+ strncpy (ifr.ifr_name, dev, sizeof(ifr.ifr_name));
+ CHECK(ioctl(sock, SIOCGIFINDEX, &ifr));
+
+ addr.sll_family = AF_PACKET;
+ addr.sll_protocol = htons(ETH_P_ALL);
+ addr.sll_ifindex = ifr.ifr_ifindex;
+
+ CHECK(bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_ll)));
+
+ struct tpacket_req req = {
+ .tp_block_size = BLOCK_SIZE,
+ .tp_frame_size = FRAME_SIZE,
+ .tp_block_nr = BLOCK_NR,
+ .tp_frame_nr = FRAME_NR,
+ };
+ CHECK(setsockopt(sock, SOL_PACKET, PACKET_RX_RING, (char *)&req, sizeof(req)));
+
+ rx_ring_buffer = (char*)CHECKPTR(mmap(0, BLOCK_SIZE*BLOCK_NR, PROT_READ|PROT_WRITE, MAP_SHARED, sock, 0));
+
+ current = 0;
+ return sock;
+}
+
+void can_rx_mmap(int sock)
+{
+ volatile struct tpacket2_hdr *hdr = rx_ring_buffer + current*FRAME_SIZE;
+
+ while (hdr->tp_status == TP_STATUS_KERNEL) {
+ struct pollfd pfd = {.fd = sock, .revents = 0,
+ .events = POLLIN|POLLRDNORM|POLLERR };
+ /* Wait for a message to arrive. If the task wake-up
+ * overhead is too high, poll() can be commented out
+ * and the application will busy-wait here. */
+ CHECK(poll(&pfd, 1, -1));
+ }
+
+ struct can_frame *cf = (void*)hdr + hdr->tp_mac;
+ printf("Frame #%d received\n", current);
+ print_can_frame(cf);
+ hdr->tp_status = 0; /* Mark the frame as processed */
+
+ current = (current + 1) % FRAME_NR;
+}
+
+int main(int argc, char *argv[])
+{
+ const char *dev;
+ int sock;
+
+ dev = candump_parse_args(argc, argv);
+
+ sock = init_mmap_socket(dev);
+
+ while (1)
+ can_rx_mmap(sock);
+}
--- /dev/null
+/**************************************************************/
+/* CAN system calls example */
+/* Author: Michal Sojka, Czech Technical University in Prague */
+/* License: Public domain */
+/**************************************************************/
+
+#include "common.h"
+
+#include <linux/can.h>
+#include <net/if.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/ioctl.h>
+
+int init_read_socket(const char *dev)
+{
+ int sock;
+ struct sockaddr_can addr;
+ struct ifreq ifr;
+
+ sock = CHECK(socket(PF_CAN, SOCK_RAW, CAN_RAW));
+
+ strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name));
+ if (-1 == ioctl(sock, SIOCGIFINDEX, &ifr)) {
+ perror(dev);
+ exit(1);
+ }
+
+ addr.can_family = AF_CAN;
+ addr.can_ifindex = ifr.ifr_ifindex;
+
+ CHECK(bind(sock, (struct sockaddr *)&addr, sizeof(addr)));
+
+ return sock;
+}
+
+void can_read(int sock)
+{
+ struct can_frame cf;
+ int ret = read(sock, &cf, sizeof(cf));
+
+ if (ret != sizeof(cf)) {
+ perror("read");
+ exit(1);
+ }
+
+ print_can_frame(&cf);
+}
+
+int main(int argc, char *argv[])
+{
+ const char *dev;
+ int sock;
+
+ dev = candump_parse_args(argc, argv);
+
+ sock = init_read_socket(dev);
+
+ while (1)
+ can_read(sock);
+}
--- /dev/null
+/**************************************************************/
+/* CAN system calls example */
+/* Author: Michal Sojka, Czech Technical University in Prague */
+/* License: Public domain */
+/**************************************************************/
+
+#define _GNU_SOURCE
+
+#include "common.h"
+
+#include <linux/can.h>
+#include <net/if.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#define MMSG_MAX 64
+
+struct mmsghdr msgs[MMSG_MAX];
+struct iovec iovecs[MMSG_MAX];
+char bufs[MMSG_MAX][sizeof(struct can_frame)];
+
+int init_recvmmsg_socket(const char *dev)
+{
+ int sock;
+ struct sockaddr_can addr;
+ struct ifreq ifr;
+ int i;
+
+ sock = CHECK(socket(PF_CAN, SOCK_RAW, CAN_RAW));
+
+ strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name));
+ if (-1 == ioctl(sock, SIOCGIFINDEX, &ifr)) {
+ perror(dev);
+ exit(1);
+ }
+
+ addr.can_family = AF_CAN;
+ addr.can_ifindex = ifr.ifr_ifindex;
+
+ CHECK(bind(sock, (struct sockaddr *)&addr, sizeof(addr)));
+
+ memset(msgs, 0, sizeof(msgs));
+ memset(iovecs, 0, sizeof(iovecs));
+ for (i = 0; i < MMSG_MAX; i++) {
+ iovecs[i].iov_base = bufs[i];
+ iovecs[i].iov_len = sizeof(struct can_frame);
+ msgs[i].msg_hdr.msg_iov = &iovecs[i];
+ msgs[i].msg_hdr.msg_iovlen = 1;
+ }
+
+ return sock;
+}
+
+void can_recvmmsg(int sock)
+{
+ int i;
+ int received = CHECK(recvmmsg(sock, msgs, MMSG_MAX, MSG_WAITFORONE, NULL));
+
+ printf("Received %d CAN frames in one system call\n", received);
+ for (i = 0; i < received; i++)
+ print_can_frame((struct can_frame*)bufs[i]);
+}
+
+int main(int argc, char *argv[])
+{
+ const char *dev;
+ int sock;
+
+ dev = candump_parse_args(argc, argv);
+
+ sock = init_recvmmsg_socket(dev);
+
+ while (1)
+ can_recvmmsg(sock);
+}
--- /dev/null
+/**************************************************************/
+/* CAN system calls example */
+/* Author: Michal Sojka, Czech Technical University in Prague */
+/* License: Public domain */
+/**************************************************************/
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#include <linux/can.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define STRINGIFY(val) #val
+#define TOSTRING(val) STRINGIFY(val)
+
+/**
+ * Evaluate expression cmd and if its value is -1, print an error
+ * message with perror().
+ *
+ * @return Result of cmd evaluation
+ */
+#define CHECK(cmd) ({ int ret = (cmd); if (ret == -1) { perror(#cmd " line " TOSTRING(__LINE__)); exit(1); }; ret; })
+#define CHECKPTR(cmd) ({ void *ptr = (cmd); if (ptr == (void*)-1) { perror(#cmd " line " TOSTRING(__LINE__)); exit(1); }; ptr; })
+
+char *candump_parse_args(int argc, char *argv[])
+{
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s <CAN interface>\n", argv[0]);
+ exit(1);
+ }
+ return argv[1];
+}
+
+void print_can_frame(const struct can_frame *cf)
+{
+ int i;
+
+ printf("%#010x [%d]", cf->can_id, cf->can_dlc);
+ for (i = 0; i < cf->can_dlc; i++)
+ printf(" %02x", cf->data[i]);
+ printf("\n");
+}
+
+
+#endif