1 #include "isotp_conn.h" 3 #include <linux/can/raw.h> 16 #include <boost/algorithm/hex.hpp> 18 #include "logging/logging.h" 20 IsoTpSendRecv::IsoTpSendRecv(std::string can_iface_, uint16_t canaddr_rx_, uint16_t canaddr_tx_)
21 : can_iface{std::move(can_iface_)}, canaddr_rx{canaddr_rx_}, canaddr_tx{canaddr_tx_} {
22 can_socket = socket(PF_CAN, SOCK_RAW, CAN_RAW);
24 if (can_socket < -1) {
25 throw std::runtime_error(
"Unable to open socket");
28 struct can_filter filter {};
29 filter.can_id = canaddr_rx & 0x7FF;
30 filter.can_mask = 0x7FF;
31 setsockopt(can_socket, SOL_CAN_RAW, CAN_RAW_FILTER, &filter,
sizeof(filter));
35 memcpy(ifr.ifr_name, can_iface.c_str(), IFNAMSIZ);
37 if (ioctl(can_socket, SIOCGIFINDEX, &ifr) != 0) {
38 throw std::runtime_error(
"Unable to get interface index");
41 struct sockaddr_can addr {};
42 addr.can_family = AF_CAN;
43 addr.can_ifindex = ifr.ifr_ifindex;
45 if (bind(can_socket, reinterpret_cast<struct sockaddr*>(&addr),
sizeof(addr)) < 0) {
46 throw std::runtime_error(
"Unable to bind socket");
49 isotp_shims = isotp_init_shims(
nullptr, canSend,
nullptr,
this);
52 bool IsoTpSendRecv::canSend(uint32_t arbitration_id,
const uint8_t*
data, uint8_t size,
void* private_data) {
55 if ((instance ==
nullptr) || size > 8) {
59 LOG_TRACE <<
"Sending CAN message AF: 0x" << std::hex << arbitration_id <<
"; Data:";
60 LOG_TRACE <<
" " << boost::algorithm::hex(std::string(reinterpret_cast<const char*>(data), size));
62 int can_socket = instance->can_socket;
64 struct can_frame frame {};
66 frame.can_id = arbitration_id;
68 memcpy(frame.data, data, size);
70 ssize_t res = write(can_socket, &frame,
sizeof(frame));
72 LOG_ERROR <<
"CAN write error: " << strerror(errno);
75 if (res !=
sizeof(frame)) {
76 LOG_ERROR <<
"CAN write error: " << res <<
" bytes of " <<
sizeof(frame) <<
" were sent";
82 bool IsoTpSendRecv::Send(
const std::string& out) {
83 IsoTpMessage message_tx = isotp_new_send_message(canaddr_tx, reinterpret_cast<const uint8_t*>(out.c_str()),
84 static_cast<uint16_t>(out.length()));
85 IsoTpSendHandle send_handle = isotp_send(&isotp_shims, &message_tx,
nullptr);
86 if (send_handle.completed) {
87 if (send_handle.success) {
90 LOG_ERROR <<
"ISO/TP message send failed";
96 FD_SET(can_socket, &read_set);
100 if (select((can_socket + 1), &read_set,
nullptr,
nullptr,
nullptr) >= 0) {
101 if (FD_ISSET(can_socket, &read_set)) {
102 struct can_frame f {};
103 ssize_t ret = read(can_socket, &f,
sizeof(f));
105 std::cerr <<
"Error receiving CAN frame" << std::endl;
109 LOG_TRACE <<
"Reveived CAN message in Send method AF: 0x" << std::hex << f.can_id <<
"; Data:";
110 LOG_TRACE <<
" " << boost::algorithm::hex(std::string(reinterpret_cast<const char*>(f.data), f.can_dlc));
112 if (!isotp_receive_flowcontrol(&isotp_shims, &send_handle, static_cast<uint16_t>(f.can_id), f.data,
114 std::cerr <<
"IsoTp receiving error" << std::endl;
118 while (send_handle.to_send != 0) {
119 if (send_handle.gap_ms != 0) {
120 std::this_thread::sleep_for(std::chrono::milliseconds(send_handle.gap_ms));
122 if (send_handle.gap_us != 0) {
123 std::this_thread::sleep_for(std::chrono::microseconds(send_handle.gap_us));
126 if (!isotp_continue_send(&isotp_shims, &send_handle)) {
127 LOG_ERROR <<
"IsoTp sending error";
130 if (send_handle.completed) {
132 if (send_handle.gap_ms != 0) {
133 std::this_thread::sleep_for(std::chrono::milliseconds(send_handle.gap_ms));
135 if (send_handle.gap_us != 0) {
136 std::this_thread::sleep_for(std::chrono::microseconds(send_handle.gap_us));
139 if (send_handle.success) {
142 LOG_ERROR <<
"IsoTp send failed";
148 LOG_TRACE <<
"Timeout on CAN socket";
151 if (send_handle.completed) {
155 std::cerr <<
"Select failed" << std::endl;
163 bool IsoTpSendRecv::Recv(std::string* in) {
164 IsoTpReceiveHandle recv_handle = isotp_receive(&isotp_shims, canaddr_tx, canaddr_rx,
nullptr);
169 FD_SET(can_socket, &read_set);
173 if (select((can_socket + 1), &read_set,
nullptr,
nullptr,
nullptr) >= 0) {
174 if (FD_ISSET(can_socket, &read_set)) {
175 struct can_frame f {};
176 ssize_t ret = read(can_socket, &f,
sizeof(f));
178 std::cerr <<
"Error receiving CAN frame" << std::endl;
182 LOG_TRACE <<
"Reveived CAN message in Recv method AF: 0x" << std::hex << f.can_id <<
"; Data:";
183 LOG_TRACE <<
" " << boost::algorithm::hex(std::string(reinterpret_cast<const char*>(f.data), f.can_dlc));
186 IsoTpMessage message_rx = isotp_continue_receive(&isotp_shims, &recv_handle, f.can_id, f.data, f.can_dlc);
187 if (message_rx.completed && recv_handle.completed) {
188 if (!recv_handle.success) {
189 std::cerr <<
"IsoTp receiving error" << std::endl;
192 *in = std::string(reinterpret_cast<const char*>(message_rx.payload), static_cast<size_t>(message_rx.size));
196 LOG_TRACE <<
"Timeout on CAN socket";
201 LOG_ERROR <<
"Select failed";