Branch data Line data Source code
1 : : #include "CanDriver.hpp"
2 : :
3 : : #include <linux/can.h>
4 : : #include <net/if.h>
5 : : #include <sys/ioctl.h>
6 : : #include <sys/socket.h>
7 : : #include <unistd.h>
8 : :
9 : : #include <cstring>
10 : : #include <iostream>
11 : :
12 : : #include "com-middleware/src/exceptions/CanCloseException.hpp"
13 : : #include "com-middleware/src/exceptions/CanInitException.hpp"
14 : :
15 : : namespace candriver {
16 : :
17 : 0 : CanDriver::CanDriver(std::string can_interface, int32_t timeout_s)
18 : 0 : : m_canInterface(std::move(can_interface)), m_timeout_s(timeout_s) {
19 : 0 : initializeCan();
20 : 0 : };
21 : :
22 : 0 : CanDriver::~CanDriver() {
23 : : try {
24 : 0 : uninitializeCan();
25 : 0 : } catch (const std::exception &exception) {
26 : 0 : std::cout << exception.what() << "\n";
27 : 0 : }
28 : 0 : };
29 : :
30 : 0 : void CanDriver::initializeCan() {
31 : 0 : if (m_canInterface.empty()) {
32 : 0 : throw exceptions::CanInitException("Can interface is empty");
33 : : }
34 : 0 : struct sockaddr_can addr {};
35 : 0 : struct ifreq ifr {}; // interface
36 : :
37 : : // opening a socket for communicating over a CAN network
38 : : // Since SocketCAN implements a new protocol family, we pass PF_CAN as the first argument to the
39 : : // socket(2) system call there are two CAN protocols to choose from, the raw socket protocol
40 : : // (SOCK_RAW) and the broadcast manager (CAN_BCM)
41 : 0 : m_can_socket_fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
42 : 0 : if (m_can_socket_fd < 0) {
43 : 0 : throw exceptions::CanInitException("Error connecting to socket");
44 : : }
45 : :
46 : : // Setting the can interface
47 : 0 : strcpy(ifr.ifr_name, m_canInterface.c_str());
48 : : // To determine the interface index an appropriate ioctl() has to be used (0 for all)
49 : : // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
50 : 0 : ioctl(m_can_socket_fd, SIOCGIFINDEX, &ifr);
51 : :
52 : 0 : memset(&addr, 0, sizeof(addr));
53 : 0 : addr.can_family = AF_CAN;
54 : 0 : addr.can_ifindex = ifr.ifr_ifindex;
55 : :
56 : : // Timeout for read blocking
57 : 0 : struct timeval timeout {};
58 : 0 : timeout.tv_sec = m_timeout_s; // Timeout in seconds
59 : 0 : timeout.tv_usec = 0; // Microseconds
60 : 0 : setsockopt(m_can_socket_fd, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast<const char *>(&timeout),
61 : : sizeof(struct timeval));
62 : :
63 : 0 : if (bind(m_can_socket_fd, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr)) < 0) {
64 : 0 : throw exceptions::CanInitException("Error binding socket");
65 : : }
66 : 0 : }
67 : :
68 : 0 : void CanDriver::uninitializeCan() const {
69 : 0 : std::cout << "Closing socket\n";
70 : 0 : if (close(m_can_socket_fd) < 0) {
71 : 0 : throw exceptions::CanCloseException("Error closing socket");
72 : : }
73 : 0 : }
74 : :
75 : 0 : auto CanDriver::receive(can_frame *frame) const -> int32_t {
76 : 0 : return static_cast<int32_t>(::read(m_can_socket_fd, frame, sizeof(can_frame)));
77 : : }
78 : : } // namespace candriver
|