Fixposition SDK 0.0.0-heads/main-0-gde8559b
Collection of c++ libraries and apps for use with Fixposition products on Linux
Loading...
Searching...
No Matches
can.hpp
Go to the documentation of this file.
1/**
2 * \verbatim
3 * ___ ___
4 * \ \ / /
5 * \ \/ / Copyright (c) Fixposition AG (www.fixposition.com) and contributors
6 * / /\ \ License: see the LICENSE file
7 * /__/ \__\
8 * \endverbatim
9 *
10 * @file
11 * @brief Fixposition SDK: CAN bus utilities
12 *
13 * @page FPSDK_COMMON_CAN CAN bus utilities
14 *
15 * **API**: fpsdk_common/can.hpp and fpsdk::common::utils
16 *
17 * @section FPSDK_COMMON_CAN_FRAMES CAN frames (messages)
18 *
19 * - Standard frame format (SFF): 11 bits CAN ID
20 * - Extended frame format (EFF): 29 bits CAN ID
21 * - Classical CAN: 8 bytes payload
22 * - CAN FD: up to 72 bytes payload, with optional switching to a second bitrate for the payload (BRS)
23 *
24 * The cansend tool (from can-utils):
25 *
26 * cansend vcan0 123#0102030405060708 # SFF frame, 8 bytes payload
27 * cansend vcan0 12345678#0102030405060708 # EFF frame, 8 bytes payload
28 *
29 * cansend vcan0 123##0112233445566778899aabbccddeeff # SFF FD 16 bytes, no bit rate switch ("0")
30 * cansend vcan0 12345678##0112233445566778899aabbccddeeff # EFF FD 16 bytes, no bit rate switch ("0")
31 *
32 * cansend vcan0 123##1112233445566778899aabbccddeeff # SFF FD 16 bytes, with bit rate switch ("1" = BRS)
33 * cansend vcan0 12345678##1112233445566778899aabbccddeeff # EFF FD 16 bytes, with bit rate switch ("1" = BRS)
34 *
35 * cansend vcan0 123#01020304 # SFF frame, only 4 bytes payload
36 *
37 * @section FP_COMMON_CAN_TESTING Testing
38 *
39 * For testing on a normal Linux box once can use a virtual CAN device:
40 *
41 * sudo modprobe vcan
42 * sudo ip link add dev vcan0 type vcan
43 * sudo ip link set up vcan0
44 *
45 * In different terminals:
46 *
47 * candump vcan0
48 *
49 * cansend vcan0 ... # see above
50 *
51 * Setup a real can device:
52 *
53 * ip link set can0 down
54 * ip link set can0 type can bitrate 125000 dbitrate 500000 fd on fd-non-iso on restart-ms 100
55 * ip link set can0 up
56 * ip link set can0 txqueuelen 1000
57 *
58 * @section FP_COMMON_CAN_REFS References
59 *
60 * - linux/can.h, a very good read!
61 * - <https://www.kernel.org/doc/html/latest/networking/can.html>
62 *
63 */
64#ifndef __FPSDK_COMMON_CAN_HPP__
65#define __FPSDK_COMMON_CAN_HPP__
66
67/* LIBC/STL */
68#include <cstdint>
69#include <string>
70#include <vector>
71
72/* EXTERNAL */
73#include <linux/can.h>
74
75/* PACKAGE */
76#include "types.hpp"
77
78namespace fpsdk {
79namespace common {
80/**
81 * @brief CAN bus utilities
82 */
83namespace can {
84/* ****************************************************************************************************************** */
85
86/**
87 * @brief CAN frame abstraction for standard, extended and FD (and combinations thereof) CAN frames
88 */
90{
91 // clang-format off
92 uint32_t can_id_ = 0; //!< CAN ID (masked by CAN_SFF_MASK resp CAN_EFF_MASK), i.e. flags removed)
93 bool is_eff_ = false; //!< true = extended frame (29 bits ID, CAN_EFF_FLAG), false = standard frame (11 bits ID)
94 bool is_fd_ = false; //!< true = CAN FD frame (up to CANFD_MAX_DLEN bytes), false = classical frame (up to CAN_MAX_DLEN bytes)
95 bool rtr_flag_ = false; //!< Remote transmission request flag (CAN_RTR_FLAG)
96 bool err_flag_ = false; //!< Error message frame flag (CAN_ERR_FLAG)
97 bool fd_brs_ = false; //!< Use bit rate switch for a FD frame (only valid if is_fd_ = true)
98 std::size_t data_len_ = false; //!< Number of bytes in payload data: up to CAN_MAX_DLEN for classical frames (is_fd_ = false), up to CANFD_MAX_DLEN for FD frames (is_fd_ = true)
99 const uint8_t* data_ = { can_frame_.data }; //!< Pointer to data (can_frame_.data resp. fd_frame_.data)
100 // clang-format on
101
102 /**
103 * @brief Set data (data_len_ and data_ fields)
104 *
105 * @param[in] data The data
106 * @param[in] size Size of the data
107 */
108 void SetData(const uint8_t* data, const std::size_t size);
109
110 /**
111 * @brief Populate frame (this struct) from raw data
112 *
113 * On success, all the fields of the struct are set from the data.
114 *
115 * @param[in] data The data (struct can_frame or struct canfd_frame)
116 * @param[in] size Size of the data (CAN_MTU or CANFD_MTU)
117 *
118 * @returns true on success, false otherwise
119 */
120 bool RawToFrame(const uint8_t* data, const std::size_t size);
121
122 /**
123 * @brief Set raw CAN frame from frame (this struct)
124 *
125 * Updates the raw CAN frame data (below) from the flags and data (above).
126 */
128
129 /**
130 * @brief Raw CAN frame
131 */
132 union
133 {
134 struct can_frame can_frame_; //!< Classical CAN frame (is_fd_ = false)
135 struct canfd_frame fd_frame_ = { 0, 0, 0, 0, 0, { 0 } }; //!< FD CAN frame (is_fd_ = true)
136 };
137};
138
139/**
140 * @brief Raw CAN helper class using SocketCAN
141 */
143{
144 public:
145 /**
146 * @brief Constructor
147 *
148 * @param[in] device Device name (e.g. "can0")
149 */
150 RawCan(const std::string& device);
151
152 /**
153 * @brief Destructor
154 */
156
157 /**
158 * @brief Open CAN interface
159 *
160 * @returns true if device was successfully opened, false otherwise
161 */
162 bool Open();
163
164 /**
165 * @brief Set filters
166 *
167 * @param[in] filters List of filters to apply to the CAN interface
168 *
169 * @returns true if filters were applied successfully, false othwise
170 *
171 * See https://www.kernel.org/doc/html/latest/networking/can.html#raw-socket-option-can-raw-filter and linux/can.h
172 * for the can_filter struct documentation (for example, the filter flags).
173 */
174 bool SetFilters(const std::vector<struct can_filter>& filters);
175
176 /**
177 * @brief Close CAN interface
178 */
179 void Close();
180
181 /**
182 * @brief Check if CAN is open
183 *
184 * @returns true if socket is open, false otherwise
185 */
186 bool IsOpen() const;
187
188 /**
189 * @brief Get socket
190 *
191 * @returns the socket, -1 if interface is not opened
192 */
193 int GetSocket() const;
194
195 /**
196 * @brief Get last error (errno)
197 *
198 * @returns the last error (errno), 0 = no error
199 */
200 int GetErrno() const;
201
202 /**
203 * @brief Get last error string (strerror)
204 *
205 * @returns the last error string
206 */
207 std::string GetStrerror();
208
209 /**
210 * @brief Flush all pending input data
211 */
213
214 /**
215 * @brief Send raw CAN frame (standard, extended and FD, and combinations thereof)
216 *
217 * @param[in,out] frame The CAN frame to send
218 *
219 * @returns true if sent successfully, false otherwise
220 */
221 bool SendFrame(CanFrame& frame);
222
223 /**
224 * @brief Read raw classical CAN frame
225 *
226 * @param[out] frame The received frame
227 * @param[in] timeout Timeout to wait for a frame [ms], use 0 for no wait, < 0 for infinite wait (like poll())
228 *
229 * @returns true if a frame was received, false otherwise
230 */
231 bool ReadFrame(struct can_frame& frame, const int timeout = 0);
232
233 /**
234 * @brief Send raw classical CAN frame
235 *
236 * @param[in] frame The CAN frame to send
237 *
238 * @returns true if sent successfully, false otherwise
239 */
240 bool SendFrame(const struct can_frame& frame);
241
242 /**
243 * @brief Send raw CAN FD frame
244 *
245 * @param[in] frame The CAN frame to send
246 *
247 * @returns true if sent successfully, false otherwise
248 */
249 bool SendFrame(const struct canfd_frame& frame);
250
251 /**
252 * @brief Read raw CAN FD frame
253 *
254 * @param[out] frame The received frame
255 * @param[in] timeout Timeout to wait for a frame [ms], use 0 for no wait, < 0 for infinite wait (like poll())
256 *
257 * @returns true if a frame was received, false otherwise
258 */
259 bool ReadFrame(struct canfd_frame& frame, const int timeout = 0);
260
261 /**
262 * @brief Read raw CAN frame (standard, extended and FD, and combinations thereof)
263 *
264 * @param[out] frame The received frame
265 * @param[in] timeout Timeout to wait for a frame [ms], use 0 for no wait, < 0 for infinite wait (like poll())
266 *
267 * @returns true if a frame was received, false otherwise
268 */
269 bool ReadFrame(CanFrame& frame, const int timeout = 0);
270
271 protected:
272 std::string device_; //!< Device name
273 int sock_; //!< The socket to the CAN inferface
274 int saved_errno_; //!< Saved errno
275};
276
277/* ****************************************************************************************************************** */
278} // namespace can
279} // namespace common
280} // namespace fpsdk
281#endif // __FPSDK_COMMON_CAN_HPP__
Raw CAN helper class using SocketCAN.
Definition can.hpp:143
void Close()
Close CAN interface.
bool ReadFrame(struct canfd_frame &frame, const int timeout=0)
Read raw CAN FD frame.
bool Open()
Open CAN interface.
int GetSocket() const
Get socket.
void FlushInput()
Flush all pending input data.
bool SendFrame(const struct canfd_frame &frame)
Send raw CAN FD frame.
bool SendFrame(CanFrame &frame)
Send raw CAN frame (standard, extended and FD, and combinations thereof)
std::string GetStrerror()
Get last error string (strerror)
bool ReadFrame(struct can_frame &frame, const int timeout=0)
Read raw classical CAN frame.
bool IsOpen() const
Check if CAN is open.
bool SendFrame(const struct can_frame &frame)
Send raw classical CAN frame.
std::string device_
Device name.
Definition can.hpp:272
int sock_
The socket to the CAN inferface.
Definition can.hpp:273
bool ReadFrame(CanFrame &frame, const int timeout=0)
Read raw CAN frame (standard, extended and FD, and combinations thereof)
int GetErrno() const
Get last error (errno)
int saved_errno_
Saved errno.
Definition can.hpp:274
bool SetFilters(const std::vector< struct can_filter > &filters)
Set filters.
RawCan(const std::string &device)
Constructor.
Base class to prevent copy or move.
Definition types.hpp:97
Fixposition SDK.
CAN frame abstraction for standard, extended and FD (and combinations thereof) CAN frames.
Definition can.hpp:90
struct can_frame can_frame_
Classical CAN frame (is_fd_ = false)
Definition can.hpp:134
void SetData(const uint8_t *data, const std::size_t size)
Set data (data_len_ and data_ fields)
bool is_eff_
true = extended frame (29 bits ID, CAN_EFF_FLAG), false = standard frame (11 bits ID)
Definition can.hpp:93
bool fd_brs_
Use bit rate switch for a FD frame (only valid if is_fd_ = true)
Definition can.hpp:97
bool rtr_flag_
Remote transmission request flag (CAN_RTR_FLAG)
Definition can.hpp:95
const uint8_t * data_
Pointer to data (can_frame_.data resp. fd_frame_.data)
Definition can.hpp:99
bool RawToFrame(const uint8_t *data, const std::size_t size)
Populate frame (this struct) from raw data.
bool err_flag_
Error message frame flag (CAN_ERR_FLAG)
Definition can.hpp:96
struct canfd_frame fd_frame_
FD CAN frame (is_fd_ = true)
Definition can.hpp:135
bool is_fd_
true = CAN FD frame (up to CANFD_MAX_DLEN bytes), false = classical frame (up to CAN_MAX_DLEN bytes)
Definition can.hpp:94
std::size_t data_len_
Number of bytes in payload data: up to CAN_MAX_DLEN for classical frames (is_fd_ = false),...
Definition can.hpp:98
uint32_t can_id_
CAN ID (masked by CAN_SFF_MASK resp CAN_EFF_MASK), i.e. flags removed)
Definition can.hpp:92
void FrameToRaw()
Set raw CAN frame from frame (this struct)
Fixposition SDK: Common types and type helpers.