Tool Libs
UMIT-TIROL Institute of Automation and Control Engineering library collection
 
Loading...
Searching...
No Matches
can.h
1#pragma once
2#include <utils/queue.h>
3#include <comm/can.h>
4#include <linux/can.h>
5#include <net/if.h>
6#include <sys/ioctl.h>
7#include <cstring>
8#include <cstdlib>
9#include <cerrno>
10#include <fcntl.h>
11#include <stdio.h>
12#include <unistd.h>
13
14namespace CAN {
15 struct HW : public CAN {
16 int sock{};
19 HW( const char *ifname ) {
20 /* open CAN_RAW socket */
21 sock = socket(PF_CAN, SOCK_RAW, CAN_RAW);
22 /* set NONBLOCK */
23 int flags = fcntl(sock, F_GETFL, 0);
24 if (flags == -1) {
25 perror("cannot get CAN socket flags");
26 return;
27 }
28 if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) {
29 perror("cannot set O_NONBLOCK on CAN socket");
30 return;
31 }
32 /* */
33 struct ifreq ifr = {};
34 strncpy(ifr.ifr_name, ifname, IF_NAMESIZE);
35 if (ioctl(sock, SIOCGIFINDEX, &ifr) == -1) {
36 perror("cannot find CAN interface index");
37 return;
38 }
39 /* setup address for bind */
40 struct sockaddr_can addr {
41 .can_family = PF_CAN,
42 .can_ifindex = ifr.ifr_ifindex,
43 };
44 /* bind socket to the can0 interface */
45 if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
46 perror("cannot bind socket to CAN interface");
47 return;
48 }
49 }
50 ~HW() {
51 close(sock);
52 }
53 bool full() override {
54 return tx.full();
55 }
56 void push(Message &&msg) override {
57 struct can_frame frame = frameFromMessage(std::move(msg));
58 tx.push(frame);
59 process();
60 }
61 void process() {
62 // transmit side
63 while (!tx.empty()) {
64 auto frame = tx.front();
65 int l = write(sock, &frame, sizeof(frame));
66 if (l < 0) {
67 if (errno != EAGAIN) {
68 perror("writing on CAN socket error");
69 }
70 break;
71 } else if ((size_t)l < sizeof(frame)) {
72 fprintf(stderr, "write: incomplete CAN frame: %d\n", l);
73 } else { // success
74 tx.pop();
75 }
76 }
77 // receive side
78 empty();
79 }
80 using Sink::push;
81 Message pop() override {
82 return rx.pop();
83 }
84 bool empty() override {
85 struct can_frame frame;
86 int l = read(sock, &frame, sizeof(frame));
87 if (l < 0) {
88 if (errno != EAGAIN) {
89 perror("reading on CAN socket error");
90 }
91 return rx.empty();
92 } else if ((size_t)l < sizeof(frame)) { /* paranoid check ... */
93 fprintf(stderr, "read: incomplete CAN frame: %d\n", l);
94 return rx.empty();
95 }
96 Message msg = messageFromFrame(frame);
97 rx.push(msg);
98 return false;
99 }
100 struct can_frame frameFromMessage(Message &&msg) {
101 struct can_frame f {};
102 f.can_id = msg.id;
103 if (msg.opts.rtr) f.can_id |= CAN_RTR_FLAG;
104 f.len = msg.opts.dlc;
105 for (int i = 0; i < f.len; ++i) {
106 f.data[i] = ((uint8_t*)&msg.data)[i];
107 }
108 return f;
109 }
110 Message messageFromFrame(struct can_frame frame) {
111 Message msg {
112 .id = frame.can_id & ((1<<30)-1),
113 .opts = {
114 .rtr = !!(frame.can_id & CAN_RTR_FLAG),
115 .dlc = frame.len,
116 },
117 };
118 for (int i = 0; i < frame.len; ++i) {
119 ((uint8_t*)&msg.data)[i] = frame.data[i];
120 }
121 return msg;
122 }
123 };
124}
simple Buffer backed queue implementation
Definition queue.h:12
T pop() override
remove front of queue and return it
Definition queue.h:65
bool empty() override
check if queue is empty
Definition queue.h:83
bool full() override
return true if queue is full
Definition queue.h:87
void push(T &&val) override
move element into queue
Definition queue.h:49
T & front()
return reference to first element in queue
Definition queue.h:55
Copyright (c) 2023 IACE.
CAN peripheral driver.
Definition can.h:15
Message pop() override
pull object from source does not check for data. guard by using 'if (!empty) { ......
Definition can.h:81
bool full() override
check if sink is full
Definition can.h:53
bool empty() override
check if source is empty
Definition can.h:84
virtual void push(const T &t)
copy semantics does not check for space. guard by using 'if (!full) { ... }'
Definition streams.h:20