socketcan_hal/lib.rs
1//! SocketCAN support.
2//!
3//! The Linux kernel supports using CAN-devices through a network-like API
4//! (see <https://www.kernel.org/doc/Documentation/networking/can.txt>). This
5//! crate allows easy access to this functionality without having to wrestle
6//! libc calls.
7//!
8//! # An introduction to CAN
9//!
10//! The CAN bus was originally designed to allow microcontrollers inside a
11//! vehicle to communicate over a single shared bus. Messages called
12//! *frames* are multicast to all devices on the bus.
13//!
14//! Every frame consists of an ID and a payload of up to 8 bytes. If two
15//! devices attempt to send a frame at the same time, the device with the
16//! higher ID will notice the conflict, stop sending and reattempt to sent its
17//! frame in the next time slot. This means that the lower the ID, the higher
18//! the priority. Since most devices have a limited buffer for outgoing frames,
19//! a single device with a high priority (== low ID) can block communication
20//! on that bus by sending messages too fast.
21//!
22//! The Linux socketcan subsystem makes the CAN bus available as a regular
23//! networking device. Opening an network interface allows receiving all CAN
24//! messages received on it. A device CAN be opened multiple times, every
25//! client will receive all CAN frames simultaneously.
26//!
27//! Similarly, CAN frames can be sent to the bus by multiple client
28//! simultaneously as well.
29//!
30//! # Hardware and more information
31//!
32//! More information on CAN [can be found on Wikipedia](). When not running on
33//! an embedded platform with already integrated CAN components,
34//! [Thomas Fischl's USBtin](http://www.fischl.de/usbtin/) (see
35//! [section 2.4](http://www.fischl.de/usbtin/#socketcan)) is one of many ways
36//! to get started.
37//!
38//! # RawFd
39//!
40//! Raw access to the underlying file descriptor and construction through
41//! is available through the `AsRawFd`, `IntoRawFd` and `FromRawFd`
42//! implementations.
43//!
44//! # Crate Features
45//!
46//! ### Default
47//!
48//! * **netlink** -
49//! Whether to include programmable CAN interface configuration capabilities
50//! based on netlink kernel communications. This brings in the
51//! [neli](https://docs.rs/neli/latest/neli/) library and its dependencies.
52//!
53//! ### Non-default
54//!
55//! * **utils** -
56//! Whether to build command-line utilities. This brings in additional
57//! dependencies like [anyhow](https://docs.rs/anyhow/latest/anyhow/) and
58//! [clap](https://docs.rs/clap/latest/clap/)
59//!
60
61// clippy: do not warn about things like "SocketCAN" inside the docs
62#![allow(clippy::doc_markdown)]
63
64mod err;
65pub use err::{CanError, CanErrorDecodingFailure, CanSocketOpenError, ConstructionError};
66
67pub mod dump;
68
69mod util;
70
71#[cfg(feature = "netlink")]
72mod nl;
73
74#[cfg(feature = "netlink")]
75pub use nl::CanInterface;
76
77#[cfg(test)]
78mod tests;
79
80use libc::{socket, SOCK_RAW, close, bind, sockaddr, read,
81 write, SOL_SOCKET, SO_RCVTIMEO, timespec, timeval, EINPROGRESS, SO_SNDTIMEO, time_t,
82 suseconds_t, fcntl, F_GETFL, F_SETFL, O_NONBLOCK};
83use itertools::Itertools;
84use nix::net::if_::if_nametoindex;
85use std::{
86 os::raw::{c_int, c_short, c_void, c_uint, c_ulong},
87 fmt,
88 io,
89 time,
90 mem::size_of,
91};
92use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
93use util::{set_socket_option, set_socket_option_mult};
94
95/// Check an error return value for timeouts.
96///
97/// Due to the fact that timeouts are reported as errors, calling `read_frame`
98/// on a socket with a timeout that does not receive a frame in time will
99/// result in an error being returned. This trait adds a `should_retry` method
100/// to `Error` and `Result` to check for this condition.
101pub trait ShouldRetry {
102 /// Check for timeout
103 ///
104 /// If `true`, the error is probably due to a timeout.
105 fn should_retry(&self) -> bool;
106}
107
108impl ShouldRetry for io::Error {
109 fn should_retry(&self) -> bool {
110 match self.kind() {
111 // EAGAIN, EINPROGRESS and EWOULDBLOCK are the three possible codes
112 // returned when a timeout occurs. the stdlib already maps EAGAIN
113 // and EWOULDBLOCK os WouldBlock
114 io::ErrorKind::WouldBlock => true,
115 // however, EINPROGRESS is also valid
116 io::ErrorKind::Other => {
117 if let Some(i) = self.raw_os_error() {
118 i == EINPROGRESS
119 } else {
120 false
121 }
122 }
123 _ => false,
124 }
125 }
126}
127
128impl<E: fmt::Debug> ShouldRetry for io::Result<E> {
129 fn should_retry(&self) -> bool {
130 if let Err(ref e) = *self {
131 e.should_retry()
132 } else {
133 false
134 }
135 }
136}
137
138// constants stolen from C headers
139const AF_CAN: c_int = 29;
140const PF_CAN: c_int = 29;
141const CAN_RAW: c_int = 1;
142const SOL_CAN_BASE: c_int = 100;
143const SOL_CAN_RAW: c_int = SOL_CAN_BASE + CAN_RAW;
144const CAN_RAW_FILTER: c_int = 1;
145const CAN_RAW_ERR_FILTER: c_int = 2;
146const CAN_RAW_LOOPBACK: c_int = 3;
147const CAN_RAW_RECV_OWN_MSGS: c_int = 4;
148// unused:
149// const CAN_RAW_FD_FRAMES: c_int = 5;
150const CAN_RAW_JOIN_FILTERS: c_int = 6;
151
152
153// get timestamp in a struct timeval (us accuracy)
154// const SIOCGSTAMP: c_int = 0x8906;
155
156// get timestamp in a struct timespec (ns accuracy)
157const SIOCGSTAMPNS: c_int = 0x8907;
158
159/// if set, indicate 29 bit extended format
160pub const EFF_FLAG: u32 = 0x80000000;
161
162/// remote transmission request flag
163pub const RTR_FLAG: u32 = 0x40000000;
164
165/// error flag
166pub const ERR_FLAG: u32 = 0x20000000;
167
168/// valid bits in standard frame id
169pub const SFF_MASK: u32 = 0x000007ff;
170
171/// valid bits in extended frame id
172pub const EFF_MASK: u32 = 0x1fffffff;
173
174/// valid bits in error frame
175pub const ERR_MASK: u32 = 0x1fffffff;
176
177
178/// an error mask that will cause SocketCAN to report all errors
179pub const ERR_MASK_ALL: u32 = ERR_MASK;
180
181/// an error mask that will cause SocketCAN to silently drop all errors
182pub const ERR_MASK_NONE: u32 = 0;
183
184fn c_timeval_new(t: time::Duration) -> timeval {
185 timeval {
186 tv_sec: t.as_secs() as time_t,
187 tv_usec: t.subsec_micros() as suseconds_t,
188 }
189}
190
191#[derive(Debug)]
192#[repr(C)]
193struct CanAddr {
194 _af_can: c_short,
195 if_index: c_int, // address familiy,
196 rx_id: u32,
197 tx_id: u32,
198}
199
200/// A socket for a CAN device.
201///
202/// Will be closed upon deallocation. To close manually, use std::drop::Drop.
203/// Internally this is just a wrapped file-descriptor.
204#[derive(Debug)]
205pub struct CanSocket {
206 fd: c_int,
207}
208
209impl CanSocket {
210 /// Open a named CAN device.
211 ///
212 /// Usually the more common case, opens a socket can device by name, such
213 /// as "vcan0" or "socan0".
214 pub fn open(ifname: &str) -> Result<CanSocket, CanSocketOpenError> {
215 let if_index = if_nametoindex(ifname)?;
216 CanSocket::open_if(if_index)
217 }
218
219 /// Open CAN device by interface number.
220 ///
221 /// Opens a CAN device by kernel interface number.
222 pub fn open_if(if_index: c_uint) -> Result<CanSocket, CanSocketOpenError> {
223 let addr = CanAddr {
224 _af_can: AF_CAN as c_short,
225 if_index: if_index as c_int,
226 rx_id: 0, // ?
227 tx_id: 0, // ?
228 };
229
230 // open socket
231 let sock_fd;
232 unsafe {
233 sock_fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
234 }
235
236 if sock_fd == -1 {
237 return Err(CanSocketOpenError::from(io::Error::last_os_error()));
238 }
239
240 // bind it
241 let bind_rv;
242 unsafe {
243 let sockaddr_ptr = &addr as *const CanAddr;
244 bind_rv = bind(sock_fd,
245 sockaddr_ptr as *const sockaddr,
246 size_of::<CanAddr>() as u32);
247 }
248
249 // FIXME: on fail, close socket (do not leak socketfds)
250 if bind_rv == -1 {
251 let e = io::Error::last_os_error();
252 unsafe {
253 close(sock_fd);
254 }
255 return Err(CanSocketOpenError::from(e));
256 }
257
258 Ok(CanSocket { fd: sock_fd })
259 }
260
261 fn close(&mut self) -> io::Result<()> {
262 unsafe {
263 let rv = close(self.fd);
264 if rv != -1 {
265 return Err(io::Error::last_os_error());
266 }
267 }
268 Ok(())
269 }
270
271 /// Change socket to non-blocking mode
272 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
273 // retrieve current flags
274 let oldfl = unsafe { fcntl(self.fd, F_GETFL) };
275
276 if oldfl == -1 {
277 return Err(io::Error::last_os_error());
278 }
279
280 let newfl = if nonblocking {
281 oldfl | O_NONBLOCK
282 } else {
283 oldfl & !O_NONBLOCK
284 };
285
286 let rv = unsafe { fcntl(self.fd, F_SETFL, newfl) };
287
288 if rv != 0 {
289 return Err(io::Error::last_os_error());
290 }
291 Ok(())
292 }
293
294 /// Sets the read timeout on the socket
295 ///
296 /// For convenience, the result value can be checked using
297 /// `ShouldRetry::should_retry` when a timeout is set.
298 pub fn set_read_timeout(&self, duration: time::Duration) -> io::Result<()> {
299 set_socket_option(self.fd, SOL_SOCKET, SO_RCVTIMEO, &c_timeval_new(duration))
300 }
301
302 /// Sets the write timeout on the socket
303 pub fn set_write_timeout(&self, duration: time::Duration) -> io::Result<()> {
304 set_socket_option(self.fd, SOL_SOCKET, SO_SNDTIMEO, &c_timeval_new(duration))
305 }
306
307 /// Blocking read a single can frame.
308 pub fn read_frame(&self) -> io::Result<CanFrame> {
309 let mut frame = CanFrame {
310 _id: 0,
311 _data_len: 0,
312 _pad: 0,
313 _res0: 0,
314 _res1: 0,
315 _data: [0; 8],
316 };
317
318 let read_rv = unsafe {
319 let frame_ptr = &mut frame as *mut CanFrame;
320 read(self.fd, frame_ptr as *mut c_void, size_of::<CanFrame>())
321 };
322
323 if read_rv as usize != size_of::<CanFrame>() {
324 return Err(io::Error::last_os_error());
325 }
326
327 Ok(frame)
328 }
329
330 /// Blocking read a single can frame with timestamp
331 ///
332 /// Note that reading a frame and retrieving the timestamp requires two
333 /// consecutive syscalls. To avoid race conditions, exclusive access
334 /// to the socket is enforce through requiring a `mut &self`.
335 pub fn read_frame_with_timestamp(&mut self) -> io::Result<(CanFrame, time::SystemTime)> {
336 let frame = self.read_frame()?;
337
338 let mut ts = timespec { tv_sec: 0, tv_nsec: 0 };
339 let rval = unsafe {
340 libc::ioctl(self.fd, SIOCGSTAMPNS as c_ulong, &mut ts as *mut timespec)
341 };
342
343 if rval == -1 {
344 return Err(io::Error::last_os_error());
345 }
346
347 Ok((frame, util::system_time_from_timespec(ts)))
348 }
349
350 /// Write a single can frame.
351 ///
352 /// Note that this function can fail with an `EAGAIN` error or similar.
353 /// Use `write_frame_insist` if you need to be sure that the message got
354 /// sent or failed.
355 pub fn write_frame(&self, frame: &CanFrame) -> io::Result<()> {
356 // not a mutable reference needed (see std::net::UdpSocket) for
357 // a comparison
358 // debug!("Sending: {:?}", frame);
359
360 let write_rv = unsafe {
361 let frame_ptr = frame as *const CanFrame;
362 write(self.fd, frame_ptr as *const c_void, size_of::<CanFrame>())
363 };
364
365 if write_rv as usize != size_of::<CanFrame>() {
366 return Err(io::Error::last_os_error());
367 }
368
369 Ok(())
370 }
371
372 /// Blocking write a single can frame, retrying until it gets sent
373 /// successfully.
374 pub fn write_frame_insist(&self, frame: &CanFrame) -> io::Result<()> {
375 loop {
376 match self.write_frame(frame) {
377 Ok(v) => return Ok(v),
378 Err(e) => {
379 if !e.should_retry() {
380 return Err(e);
381 }
382 }
383 }
384 }
385 }
386
387 /// Sets filters on the socket.
388 ///
389 /// CAN packages received by SocketCAN are matched against these filters,
390 /// only matching packets are returned by the interface.
391 ///
392 /// See `CanFilter` for details on how filtering works. By default, all
393 /// single filter matching all incoming frames is installed.
394 pub fn set_filters(&self, filters: &[CanFilter]) -> io::Result<()> {
395 set_socket_option_mult(self.fd, SOL_CAN_RAW, CAN_RAW_FILTER, filters)
396 }
397
398 /// Sets the error mask on the socket.
399 ///
400 /// By default (`ERR_MASK_NONE`) no error conditions are reported as
401 /// special error frames by the socket. Enabling error conditions by
402 /// setting `ERR_MASK_ALL` or another non-empty error mask causes the
403 /// socket to receive notification about the specified conditions.
404 #[inline]
405 pub fn set_error_mask(&self, mask: u32) -> io::Result<()> {
406 set_socket_option(self.fd, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &mask)
407 }
408
409 /// Enable or disable loopback.
410 ///
411 /// By default, loopback is enabled, causing other applications that open
412 /// the same CAN bus to see frames emitted by different applications on
413 /// the same system.
414 #[inline]
415 pub fn set_loopback(&self, enabled: bool) -> io::Result<()> {
416 let loopback: c_int = if enabled { 1 } else { 0 };
417 set_socket_option(self.fd, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback)
418 }
419
420 /// Enable or disable receiving of own frames.
421 ///
422 /// When loopback is enabled, this settings controls if CAN frames sent
423 /// are received back immediately by sender. Default is off.
424 pub fn set_recv_own_msgs(&self, enabled: bool) -> io::Result<()> {
425 let recv_own_msgs: c_int = if enabled { 1 } else { 0 };
426 set_socket_option(self.fd, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &recv_own_msgs)
427 }
428
429 /// Enable or disable join filters.
430 ///
431 /// By default a frame is accepted if it matches any of the filters set
432 /// with `set_filters`. If join filters is enabled, a frame has to match
433 /// _all_ filters to be accepted.
434 pub fn set_join_filters(&self, enabled: bool) -> io::Result<()> {
435 let join_filters: c_int = if enabled { 1 } else { 0 };
436 set_socket_option(self.fd, SOL_CAN_RAW, CAN_RAW_JOIN_FILTERS, &join_filters)
437 }
438}
439
440impl AsRawFd for CanSocket {
441 fn as_raw_fd(&self) -> RawFd {
442 self.fd
443 }
444}
445
446impl FromRawFd for CanSocket {
447 unsafe fn from_raw_fd(fd: RawFd) -> CanSocket {
448 CanSocket { fd, }
449 }
450}
451
452impl IntoRawFd for CanSocket {
453 fn into_raw_fd(self) -> RawFd {
454 self.fd
455 }
456}
457
458impl Drop for CanSocket {
459 fn drop(&mut self) {
460 self.close().ok(); // ignore result
461 }
462}
463
464/// CanFrame
465///
466/// Uses the same memory layout as the underlying kernel struct for performance
467/// reasons.
468#[derive(Debug, Copy, Clone)]
469#[repr(C)]
470pub struct CanFrame {
471 /// 32 bit CAN_ID + EFF/RTR/ERR flags
472 _id: u32,
473
474 /// data length. Bytes beyond are not valid
475 _data_len: u8,
476
477 /// padding
478 _pad: u8,
479
480 /// reserved
481 _res0: u8,
482
483 /// reserved
484 _res1: u8,
485
486 /// buffer for data
487 _data: [u8; 8],
488}
489
490impl CanFrame {
491 pub fn new(id: u32, data: &[u8], rtr: bool, err: bool) -> Result<CanFrame, ConstructionError> {
492 let mut _id = id;
493
494 if data.len() > 8 {
495 return Err(ConstructionError::TooMuchData);
496 }
497
498 if id > EFF_MASK {
499 return Err(ConstructionError::IDTooLarge);
500 }
501
502 // set EFF_FLAG on large message
503 if id > SFF_MASK {
504 _id |= EFF_FLAG;
505 }
506
507
508 if rtr {
509 _id |= RTR_FLAG;
510 }
511
512 if err {
513 _id |= ERR_FLAG;
514 }
515
516 let mut full_data = [0; 8];
517
518 // not cool =/
519 for (n, c) in data.iter().enumerate() {
520 full_data[n] = *c;
521 }
522
523 Ok(CanFrame {
524 _id,
525 _data_len: data.len() as u8,
526 _pad: 0,
527 _res0: 0,
528 _res1: 0,
529 _data: full_data,
530 })
531 }
532
533 /// Return the actual CAN ID (without EFF/RTR/ERR flags)
534 #[inline]
535 pub fn id(&self) -> u32 {
536 if self.is_extended() {
537 self._id & EFF_MASK
538 } else {
539 self._id & SFF_MASK
540 }
541 }
542
543 /// Return the error message
544 #[inline]
545 pub fn err(&self) -> u32 {
546 self._id & ERR_MASK
547 }
548
549 /// Check if frame uses 29 bit extended frame format
550 #[inline]
551 pub fn is_extended(&self) -> bool {
552 self._id & EFF_FLAG != 0
553 }
554
555 /// Check if frame is an error message
556 #[inline]
557 pub fn is_error(&self) -> bool {
558 self._id & ERR_FLAG != 0
559 }
560
561 /// Check if frame is a remote transmission request
562 #[inline]
563 pub fn is_rtr(&self) -> bool {
564 self._id & RTR_FLAG != 0
565 }
566
567 /// A slice into the actual data. Slice will always be <= 8 bytes in length
568 #[inline]
569 pub fn data(&self) -> &[u8] {
570 &self._data[..(self._data_len as usize)]
571 }
572
573 /// Read error from message and transform it into a `CanError`.
574 ///
575 /// SocketCAN errors are indicated using the error bit and coded inside
576 /// id and data payload. Call `error()` converts these into usable
577 /// `CanError` instances.
578 ///
579 /// If the frame is malformed, this may fail with a
580 /// `CanErrorDecodingFailure`.
581 #[inline]
582 pub fn error(&self) -> Result<CanError, CanErrorDecodingFailure> {
583 CanError::from_frame(self)
584 }
585}
586
587impl fmt::UpperHex for CanFrame {
588 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
589 write!(f, "{:X}#", self.id())?;
590
591 let mut parts = self.data().iter().map(|v| format!("{:02X}", v));
592
593 let sep = if f.alternate() { " " } else { "" };
594 write!(f, "{}", parts.join(sep))
595 }
596}
597
598/// CanFilter
599///
600/// Contains an internal id and mask. Packets are considered to be matched by
601/// a filter if `received_id & mask == filter_id & mask` holds true.
602#[derive(Debug, Copy, Clone)]
603#[repr(C)]
604pub struct CanFilter {
605 _id: u32,
606 _mask: u32,
607}
608
609impl CanFilter {
610 /// Construct a new CAN filter.
611 pub fn new(id: u32, mask: u32) -> Result<CanFilter, ConstructionError> {
612 Ok(CanFilter {
613 _id: id,
614 _mask: mask,
615 })
616 }
617}