2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
29#include <linux/can/raw.h>
32#include <sys/socket.h>
51#include "exceptions/CanCloseException.hpp"
52#include "exceptions/CanException.hpp"
53#include "exceptions/CanInitException.hpp"
54#include "exceptions/InvalidSocketException.hpp"
67 using std::unique_lock;
68 using std::unique_ptr;
69 using std::chrono::milliseconds;
70 using std::this_thread::sleep_for;
78#pragma region "Object Construction"
79 CanDriver::CanDriver(
const string& canInterface, int32_t canProtocol,
const CanId defaultSenderId):
82 CanDriver::
CanDriver(
const string& canInterface,
const int32_t canProtocol,
const int32_t filterMask,
const CanId defaultSenderId):
83 CanDriver(canInterface
, canProtocol
, filtermap_t{{0, filterMask}}
, defaultSenderId
) { }
85 CanDriver::
CanDriver(
const string& canInterface,
const int32_t canProtocol,
const filtermap_t& filters,
const CanId defaultSenderId):
93
94
95
96
97
98
99
103 unique_lock<mutex> locky(
_lock);
105 fd_set readFileDescriptors;
106 timeval waitTime{0,
static_cast<suseconds_t>(timeout.count())};
108 FD_ZERO(&readFileDescriptors);
110 const auto fdsAvailable = select(
_socketFd + 1, &readFileDescriptors,
nullptr,
nullptr, &waitTime);
112 int32_t bytesAvailable{0};
113 const auto retCode = ioctl(
_socketFd, FIONREAD, &bytesAvailable);
115 _queueSize =
static_cast<int32_t>(std::ceil(bytesAvailable /
sizeof(can_frame)));
123 return fdsAvailable > 0;
127
128
129
130
131
132
133
137
138
139
140
141
142
143
147
148
149
150
154
155
156
157
159 unique_ptr<unique_lock<mutex>> locky{
nullptr};
161 if (lock) { locky = unique_ptr<unique_lock<mutex>>{
new unique_lock<mutex>{
_lock}}; }
165 ssize_t readBytes{0};
166 can_frame canFrame{};
168 readBytes = read(
_socketFd, &canFrame,
sizeof(can_frame));
176
177
178
179
180
181
182
188 ssize_t bytesWritten = 0;
196 if (forceExtended || ((uint32_t)message
.getCanId() > CAN_SFF_MASK)) { canFrame.can_id |= CAN_EFF_FLAG; }
198 bytesWritten = write(
_socketFd, (
const void*)&canFrame,
sizeof(canFrame));
206
207
208
209
210
211
212
213
217
218
219
220
221
222
223
224
228
229
230
231
232
233
234
235
239 ssize_t totalBytesWritten = 0;
241 while (!messages.empty()) {
242 totalBytesWritten +=
sendMessage(messages.front()
, forceExtended
);
245 if (delay.count() > 0) {
250 return totalBytesWritten;
254
255
256
257
261 unique_lock<mutex> locky{
_lock};
275 can_frame canFrame{};
276 readBytes = read(
_socketFd, &canFrame,
sizeof(can_frame));
277 if (readBytes >= 0) {
278 messages.emplace(canFrame);
279 }
else if (errno == EAGAIN) {
291
292
293
294
295
296
300 int32_t canFdFrames = enabled ? 1 : 0;
302 if (setsockopt(
_socketFd, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &canFdFrames,
sizeof(canFdFrames)) == -1) {
309
310
311
312
313
314
315 void CanDriver::allowCanXlFrames(
const bool enabled)
const {
318 int32_t canXlFrames = enabled ? 1 : 0;
321 if (setsockopt(
_socketFd, SOL_CAN_RAW, CAN_RAW_XL_FRAMES, &canXlFrames,
sizeof(canXlFrames)) == -1) {
328
329
330
331
332
336 int32_t joinFilters = 1;
338 if (setsockopt(
_socketFd, SOL_CAN_RAW, CAN_RAW_JOIN_FILTERS, &joinFilters,
sizeof(joinFilters)) == -1) {
344
345
346
347
348
352
353
354
355
359 unique_lock<mutex> locky(
_lock);
360 vector<can_filter> canFilters{};
363 #if __cplusplus
>= 201703L
364 for (
const auto [id, filter] : filters) {
365 canFilters.push_back({
*id, filter});
368 for (
const auto& filterPair : filters) {
369 canFilters.push_back({*filterPair.first, filterPair.second});
373 if (setsockopt(
_socketFd, SOL_CAN_RAW, CAN_RAW_FILTER, canFilters.data(), canFilters.size() *
sizeof(can_filter)) == -1) {
379
380
381
382
386 int32_t errorFilter = enabled ? 1 : 0;
388 if (setsockopt(
_socketFd, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &errorFilter,
sizeof(errorFilter)) == -1) {
394
395
396
397
398
399
403 int32_t receiveOwnMessages = enabled ? 1 : 0;
405 if (setsockopt(
_socketFd, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &receiveOwnMessages,
sizeof(receiveOwnMessages)) == -1) {
415#pragma region Socket Management
418
419
421 struct sockaddr_can address{};
422 struct ifreq ifaceRequest{};
423 int64_t fdOptions{0};
424 int32_t tmpReturn{0};
434 if ((tmpReturn = ioctl(
_socketFd, SIOCGIFINDEX, &ifaceRequest)) == -1) {
440 fdOptions |= O_NONBLOCK;
441 tmpReturn = fcntl(
_socketFd, F_SETFL, fdOptions);
443 address.can_family = AF_CAN;
444 address.can_ifindex = ifaceRequest.ifr_ifindex;
448 if ((tmpReturn = bind(
_socketFd, (
struct sockaddr*)&address,
sizeof(address))) == -1) {
454
455
457 unique_lock<mutex> locky(
_lock);
CanDriver class; handles communication via CAN.
virtual void allowCanFdFrames(const bool enabled=true) const
Sets the CAN FD frame option for the interface.
virtual void joinCanFilters() const
Configures the socket to join the CAN filters.
CanDriver(const string &canInterface, const int32_t canProtocol, const filtermap_t &filters, const CanId defaultSenderId=0)
bool _canReadQueueSize
!< The size of the message queue read by waitForMessages()
virtual void setReceiveOwnMessages(const bool enabled=true) const
Sets the receive own messages option for the interface.
virtual CanMessage readMessage()
Attempts to read a single message from the bus.
virtual void setErrorFilter(const bool enabled=true) const
Sets the error filter for the interface.
CanDriver(const string &canInterface, const int32_t canProtocol, const int32_t filterMask, const CanId defaultSenderId=0)
virtual ssize_t sendMessageQueue(queue< CanMessage > &messages, milliseconds delay=20ms, bool forceExtended=false)
Attempts to send a queue of messages.
virtual void setCanFilters(const filtermap_t &filters)
Sets the CAN filters for the interface.
string _canInterface
The CAN interface used for communication (e.g. can0, can1, ...)
CanId _defaultSenderId
The ID to send messages with if no other ID was set.
virtual queue< CanMessage > readQueuedMessages()
Attempts to read all queued messages from the bus.
int32_t _canProtocol
The protocol used when communicating via CAN.
virtual void setCanFilterMask(const int32_t mask, const CanId &filterId)
Attempts to set a new CAN filter mask to the interface.
virtual CanMessage readMessageLock(bool const lock=true)
readMessage deadlock guard
virtual ssize_t sendMessage(const CanMessage &message, bool forceExtended=false)
Attempts to send a single CAN message.
virtual ssize_t sendMessageQueue(queue< CanMessage > &messages, nanoseconds delay=20ns, bool forceExtended=false)
Attempts to send a queue of messages.
int32_t _socketFd
The CAN socket file descriptor.
virtual bool waitForMessages(milliseconds timeout=3000ms)
Waits for CAN messages to appear.
mutex _lock
!< Is the queue size available
filtermap_t _canFilterMask
The bit mask used to filter CAN messages.
virtual void initialiseSocketCan()
Initialises socketcan.
static constexpr int32_t CAN_MAX_DATA_LENGTH
The maximum amount of bytes allowed in a single CAN frame.
virtual bool waitForMessages(nanoseconds timeout=3000ns)
Waits for CAN messages to appear.
virtual bool waitForMessages(microseconds timeout=3000us)
Waits for CAN messages to appear.
virtual ssize_t sendMessageQueue(queue< CanMessage > &messages, microseconds delay=20us, bool forceExtended=false)
Attempts to send a queue of messages.
virtual void uninitialiseSocketCan()
Uninitialises socketcan.
Represents a CAN message that was received.
const string getFrameData() const
const can_frame getRawFrame() const
CanMessage(const struct can_frame frame)
const CanId getCanId() const
An exception that may be thrown when an error occurs while closing a CAN socket.
CanCloseException(string message)
An exception that may be thrown when an error occurs while closing a CAN socket.
CanException(const string &message, int32_t socket)
An exception that may be thrown when an error occurred while initialising a CAN socket.
CanInitException(string message)
An exception that may be thrown when an error occurs while closing a CAN socket.
InvalidSocketException(const string &message, int32_t socket)
string formatString(const string &format, Args... args)
Formats a std string object.
Represents a CAN ID in a simple and easy-to-use manner.
constexpr canid_t operator*() const
Returns the raw CAN ID value.