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}