]> rtime.felk.cvut.cz Git - sojka/can-syscalls-examples.git/blob - cansend-mmap.c
Add cansend examples
[sojka/can-syscalls-examples.git] / cansend-mmap.c
1 /**************************************************************/
2 /* CAN system calls example                                   */
3 /* Author: Michal Sojka, Czech Technical University in Prague */
4 /* License: Public domain                                     */
5 /**************************************************************/
6
7 #include "common.h"
8
9 #include <linux/can.h>
10 #include <net/if.h>
11 #include <unistd.h>
12 #include <fcntl.h>
13 #include <stdbool.h>
14 #include <string.h>
15 #include <sys/socket.h>
16 #include <linux/if_packet.h>
17 #include <net/ethernet.h> /* the L2 protocols */
18 #include <sys/ioctl.h>
19 #include <arpa/inet.h>
20 #include <sys/mman.h>
21 #include <poll.h>
22
23 #define FRAME_SIZE 128
24 #define BLOCK_SIZE 4096
25 #define BLOCK_NR 2
26 #define FRAME_NR (BLOCK_NR*(BLOCK_SIZE/FRAME_SIZE))
27
28 void *tx_ring_buffer;
29
30 int init_mmap_socket(const char *dev)
31 {
32         int sock;
33         struct sockaddr_ll addr;
34         struct ifreq ifr;
35
36         sock = CHECK(socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)));
37
38         int val = TPACKET_V2;
39         CHECK(setsockopt(sock, SOL_PACKET, PACKET_VERSION, &val, sizeof(val)));
40
41         strncpy (ifr.ifr_name, dev, sizeof(ifr.ifr_name));
42         CHECK(ioctl(sock, SIOCGIFINDEX, &ifr));
43
44         addr.sll_family = AF_PACKET;
45         addr.sll_protocol = htons(ETH_P_CAN);
46         addr.sll_ifindex =  ifr.ifr_ifindex;
47
48         CHECK(bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_ll)));
49
50         struct tpacket_req req = {
51                 .tp_block_size = BLOCK_SIZE,
52                 .tp_frame_size = FRAME_SIZE,
53                 .tp_block_nr   = BLOCK_NR,
54                 .tp_frame_nr   = FRAME_NR,
55         };
56         CHECK(setsockopt(sock, SOL_PACKET, PACKET_TX_RING, (char *)&req, sizeof(req)));
57
58         tx_ring_buffer = (void*)CHECKPTR(mmap(0, BLOCK_SIZE*BLOCK_NR, PROT_READ|PROT_WRITE, MAP_SHARED, sock, 0));
59
60         return sock;
61 }
62
63 void can_tx_mmap(int sock, const struct can_frame *cf, int count)
64 {
65         int i;
66         for (i = 0; i < count; i++) {
67                 volatile struct tpacket2_hdr *hdr = tx_ring_buffer + i * FRAME_SIZE;
68
69                 struct can_frame *cf_mmap = (void*)hdr + TPACKET_HDRLEN  - sizeof(struct sockaddr_ll);
70                 *cf_mmap = cf[i];
71                 hdr->tp_len = sizeof(cf[i]);
72                 hdr->tp_status = TP_STATUS_SEND_REQUEST;
73         }
74
75         CHECK(send(sock, NULL, 0, 0));
76 }
77
78 int main(int argc, char *argv[])
79 {
80         const char *dev;
81         int sock, count;
82         struct can_frame cf[FRAME_NR];
83
84         dev = cansend_parse_args(argc, argv, &count, cf, FRAME_NR);
85
86         sock = init_mmap_socket(dev);
87
88         can_tx_mmap(sock, cf, count);
89         sleep(1);
90         return 0;
91 }