1 /**************************************************************/
2 /* CAN system calls example */
3 /* Author: Michal Sojka, Czech Technical University in Prague */
4 /* License: Public domain */
5 /**************************************************************/
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>
23 #define FRAME_SIZE 128
24 #define BLOCK_SIZE 4096
26 #define FRAME_NR (BLOCK_NR*(BLOCK_SIZE/FRAME_SIZE))
30 int init_mmap_socket(const char *dev)
33 struct sockaddr_ll addr;
36 sock = CHECK(socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)));
39 CHECK(setsockopt(sock, SOL_PACKET, PACKET_VERSION, &val, sizeof(val)));
41 strncpy (ifr.ifr_name, dev, sizeof(ifr.ifr_name));
42 CHECK(ioctl(sock, SIOCGIFINDEX, &ifr));
44 addr.sll_family = AF_PACKET;
45 addr.sll_protocol = htons(ETH_P_CAN);
46 addr.sll_ifindex = ifr.ifr_ifindex;
48 CHECK(bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_ll)));
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,
56 CHECK(setsockopt(sock, SOL_PACKET, PACKET_TX_RING, (char *)&req, sizeof(req)));
58 tx_ring_buffer = (void*)CHECKPTR(mmap(0, BLOCK_SIZE*BLOCK_NR, PROT_READ|PROT_WRITE, MAP_SHARED, sock, 0));
63 void can_tx_mmap(int sock, const struct can_frame *cf, int count)
66 for (i = 0; i < count; i++) {
67 volatile struct tpacket2_hdr *hdr = tx_ring_buffer + i * FRAME_SIZE;
69 struct can_frame *cf_mmap = (void*)hdr + TPACKET_HDRLEN - sizeof(struct sockaddr_ll);
71 hdr->tp_len = sizeof(cf[i]);
72 hdr->tp_status = TP_STATUS_SEND_REQUEST;
75 CHECK(send(sock, NULL, 0, 0));
78 int main(int argc, char *argv[])
82 struct can_frame cf[FRAME_NR];
84 dev = cansend_parse_args(argc, argv, &count, cf, FRAME_NR);
86 sock = init_mmap_socket(dev);
88 can_tx_mmap(sock, cf, count);