]> rtime.felk.cvut.cz Git - sojka/can-syscalls-examples.git/blobdiff - cansend-mmap.c
Add cansend examples
[sojka/can-syscalls-examples.git] / cansend-mmap.c
diff --git a/cansend-mmap.c b/cansend-mmap.c
new file mode 100644 (file)
index 0000000..e37ffd7
--- /dev/null
@@ -0,0 +1,91 @@
+/**************************************************************/
+/* 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 *tx_ring_buffer;
+
+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)));
+
+       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_CAN);
+       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_TX_RING, (char *)&req, sizeof(req)));
+
+       tx_ring_buffer = (void*)CHECKPTR(mmap(0, BLOCK_SIZE*BLOCK_NR, PROT_READ|PROT_WRITE, MAP_SHARED, sock, 0));
+
+       return sock;
+}
+
+void can_tx_mmap(int sock, const struct can_frame *cf, int count)
+{
+       int i;
+       for (i = 0; i < count; i++) {
+               volatile struct tpacket2_hdr *hdr = tx_ring_buffer + i * FRAME_SIZE;
+
+               struct can_frame *cf_mmap = (void*)hdr + TPACKET_HDRLEN  - sizeof(struct sockaddr_ll);
+               *cf_mmap = cf[i];
+               hdr->tp_len = sizeof(cf[i]);
+               hdr->tp_status = TP_STATUS_SEND_REQUEST;
+       }
+
+       CHECK(send(sock, NULL, 0, 0));
+}
+
+int main(int argc, char *argv[])
+{
+       const char *dev;
+       int sock, count;
+       struct can_frame cf[FRAME_NR];
+
+       dev = cansend_parse_args(argc, argv, &count, cf, FRAME_NR);
+
+       sock = init_mmap_socket(dev);
+
+       can_tx_mmap(sock, cf, count);
+       sleep(1);
+       return 0;
+}