socketcan_rs/
driver.rs

1use crate::{
2    c_timeval_new, raw_open_socket, raw_write_frame, set_fd_mode, set_socket_option,
3    set_socket_option_mult, CanAddr, CanAnyFrame, CanMessage,
4};
5use libc::{
6    can_filter, can_frame, canfd_frame, canxl_frame, fcntl, read, CAN_RAW_ERR_FILTER,
7    CAN_RAW_FILTER, CAN_RAW_JOIN_FILTERS, CAN_RAW_LOOPBACK, CAN_RAW_RECV_OWN_MSGS, EINPROGRESS,
8    F_GETFL, F_SETFL, O_NONBLOCK, SOL_CAN_RAW, SOL_SOCKET, SO_RCVTIMEO, SO_SNDTIMEO,
9};
10use rs_can::{CanDirect, CanError, CanFilter, CanFrame, ERR_MASK};
11use std::{
12    collections::HashMap,
13    io,
14    os::{
15        fd::{AsRawFd, BorrowedFd, FromRawFd, OwnedFd},
16        raw::{c_int, c_void},
17    },
18    sync::Arc,
19    time::{Duration, Instant},
20};
21
22pub(crate) const FRAME_SIZE: usize = std::mem::size_of::<can_frame>();
23pub(crate) const FD_FRAME_SIZE: usize = std::mem::size_of::<canfd_frame>();
24pub(crate) const XL_FRAME_SIZE: usize = std::mem::size_of::<canxl_frame>();
25
26#[derive(Debug, Clone)]
27pub struct SocketCan {
28    pub(crate) sockets: Arc<HashMap<String, OwnedFd>>,
29}
30
31impl SocketCan {
32    pub fn new() -> Self {
33        Self {
34            sockets: Default::default(),
35        }
36    }
37
38    pub fn init_channel(&mut self, channel: &str, canfd: bool) -> Result<(), CanError> {
39        let addr =
40            CanAddr::from_iface(channel).map_err(|e| CanError::InitializeError(e.to_string()))?;
41
42        let _ = raw_open_socket(&addr)
43            .and_then(|fd| set_fd_mode(fd, canfd))
44            .and_then(|fd| {
45                Arc::get_mut(&mut self.sockets)
46                    .ok_or(io::Error::last_os_error())?
47                    .insert(channel.to_owned(), unsafe { OwnedFd::from_raw_fd(fd) });
48                // Rc::get_mut(&mut self.sockets)
49                //     .ok_or(io::Error::last_os_error())?
50                //     .insert(channel.to_owned(), unsafe { OwnedFd::from_raw_fd(fd) });
51                Ok(())
52            })
53            .map_err(|_| CanError::InitializeError("device open failed".into()));
54
55        Ok(())
56    }
57
58    pub fn read(&self, channel: &str) -> Result<CanMessage, CanError> {
59        match self.sockets.get(channel) {
60            Some(s) => {
61                let mut buffer = [0; XL_FRAME_SIZE];
62
63                let rd = unsafe {
64                    read(
65                        s.as_raw_fd(),
66                        &mut buffer as *mut _ as *mut c_void,
67                        XL_FRAME_SIZE,
68                    )
69                };
70                match rd as usize {
71                    FRAME_SIZE => {
72                        let frame = unsafe { *(&buffer as *const _ as *const can_frame) };
73                        let mut frame = CanMessage::from(CanAnyFrame::from(frame));
74                        frame.set_direct(CanDirect::Receive);
75                        Ok(frame)
76                    }
77                    FD_FRAME_SIZE => {
78                        let frame = unsafe { *(&buffer as *const _ as *const canfd_frame) };
79                        let mut frame = CanMessage::from(CanAnyFrame::from(frame));
80                        frame.set_direct(CanDirect::Receive);
81                        Ok(frame)
82                    }
83                    XL_FRAME_SIZE => {
84                        let frame = unsafe { *(&buffer as *const _ as *const canxl_frame) };
85                        let mut frame = CanMessage::from(CanAnyFrame::from(frame));
86                        frame.set_direct(CanDirect::Receive);
87                        Ok(frame)
88                    }
89                    _ => Err(CanError::OperationError(
90                        io::Error::last_os_error().to_string(),
91                    )),
92                }
93            }
94            None => Err(CanError::channel_not_opened(channel)),
95        }
96    }
97
98    /// Blocking read a single can frame with timeout.
99    pub fn read_timeout(&self, channel: &str, timeout: Duration) -> Result<CanMessage, CanError> {
100        match self.sockets.get(channel) {
101            Some(s) => {
102                use nix::poll::{poll, PollFd, PollFlags};
103                let borrowed_fd = unsafe { BorrowedFd::borrow_raw(s.as_raw_fd()) };
104                let pollfd = PollFd::new(borrowed_fd, PollFlags::POLLIN);
105
106                match poll::<u16>(&mut [pollfd], timeout.as_millis() as u16)
107                    .map_err(|e| CanError::OperationError(e.to_string()))?
108                {
109                    0 => Err(CanError::channel_timeout(channel)),
110                    _ => self.read(channel),
111                }
112            }
113            None => Err(CanError::channel_not_opened(channel)),
114        }
115    }
116
117    pub fn write(&self, msg: CanMessage) -> Result<(), CanError> {
118        let channel = msg.channel();
119        match self.sockets.get(&channel) {
120            Some(s) => {
121                let frame: CanAnyFrame = msg.into();
122                match frame {
123                    CanAnyFrame::Normal(f) | CanAnyFrame::Remote(f) | CanAnyFrame::Error(f) => {
124                        raw_write_frame(s.as_raw_fd(), &f, frame.size())
125                            .map_err(|e| CanError::OtherError(e.to_string()))
126                    }
127                    CanAnyFrame::Fd(f) => raw_write_frame(s.as_raw_fd(), &f, frame.size())
128                        .map_err(|e| CanError::OtherError(e.to_string())),
129                    CanAnyFrame::Xl(f) => raw_write_frame(s.as_raw_fd(), &f, frame.size())
130                        .map_err(|e| CanError::OtherError(e.to_string())),
131                }
132            }
133            None => Err(CanError::channel_not_opened(channel)),
134        }
135    }
136
137    /// Blocking write a single can frame, retrying until it gets sent successfully.
138    pub fn write_timeout(&self, msg: CanMessage, timeout: Duration) -> Result<(), CanError> {
139        let channel = msg.channel();
140        let frame: CanAnyFrame = msg.into();
141        let start = Instant::now();
142        while start.elapsed() < timeout {
143            match self.sockets.get(&channel) {
144                Some(s) => {
145                    if let Err(e) = match frame {
146                        CanAnyFrame::Normal(f) | CanAnyFrame::Remote(f) | CanAnyFrame::Error(f) => {
147                            raw_write_frame(s.as_raw_fd(), &f, frame.size())
148                        }
149                        CanAnyFrame::Fd(f) => raw_write_frame(s.as_raw_fd(), &f, frame.size()),
150                        CanAnyFrame::Xl(f) => raw_write_frame(s.as_raw_fd(), &f, frame.size()),
151                    } {
152                        match e.kind() {
153                            io::ErrorKind::WouldBlock => {}
154                            io::ErrorKind::Other => {
155                                if !matches!(e.raw_os_error(), Some(errno) if errno == EINPROGRESS)
156                                {
157                                    return Err(CanError::OperationError(e.to_string()));
158                                }
159                            }
160                            _ => return Err(CanError::OperationError(e.to_string())),
161                        }
162                    } else {
163                        return Ok(());
164                    }
165                }
166                None => return Err(CanError::channel_not_opened(channel)),
167            }
168        }
169
170        Err(CanError::channel_timeout(channel))
171    }
172
173    /// Change socket to non-blocking mode or back to blocking mode.
174    pub fn set_nonblocking(&self, channel: &str, nonblocking: bool) -> Result<(), CanError> {
175        match self.sockets.get(channel) {
176            Some(s) => {
177                // retrieve current flags
178                let oldfl = unsafe { fcntl(s.as_raw_fd(), F_GETFL) };
179
180                if oldfl == -1 {
181                    return Err(CanError::OperationError(
182                        io::Error::last_os_error().to_string(),
183                    ));
184                }
185
186                let newfl = if nonblocking {
187                    oldfl | O_NONBLOCK
188                } else {
189                    oldfl & !O_NONBLOCK
190                };
191
192                let ret = unsafe { fcntl(s.as_raw_fd(), F_SETFL, newfl) };
193
194                if ret != 0 {
195                    Err(CanError::OperationError(
196                        io::Error::last_os_error().to_string(),
197                    ))
198                } else {
199                    Ok(())
200                }
201            }
202            None => Err(CanError::channel_not_opened(channel)),
203        }
204    }
205
206    /// Sets the read timeout on the socket
207    ///
208    /// For convenience, the result value can be checked using
209    /// `ShouldRetry::should_retry` when a timeout is set.
210    pub fn set_read_timeout(&self, channel: &str, duration: Duration) -> Result<(), CanError> {
211        match self.sockets.get(channel) {
212            Some(s) => set_socket_option(
213                s.as_raw_fd(),
214                SOL_SOCKET,
215                SO_RCVTIMEO,
216                &c_timeval_new(duration),
217            )
218            .map_err(|e| CanError::OperationError(e.to_string())),
219            None => Err(CanError::channel_not_opened(channel)),
220        }
221    }
222
223    /// Sets the write timeout on the socket
224    pub fn set_write_timeout(&self, channel: &str, duration: Duration) -> Result<(), CanError> {
225        match self.sockets.get(channel) {
226            Some(s) => set_socket_option(
227                s.as_raw_fd(),
228                SOL_SOCKET,
229                SO_SNDTIMEO,
230                &c_timeval_new(duration),
231            )
232            .map_err(|e| CanError::OperationError(e.to_string())),
233            None => Err(CanError::channel_not_opened(channel)),
234        }
235    }
236}
237
238impl SocketCan {
239    /// Sets CAN ID filters on the socket.
240    ///
241    /// CAN packages received by SocketCAN are matched against these filters,
242    /// only matching packets are returned by the interface.
243    ///
244    /// See `CanFilter` for details on how filtering works. By default, all
245    /// single filter matching all incoming frames is installed.
246    pub fn set_filters(&self, channel: &str, filters: &[CanFilter]) -> Result<(), CanError> {
247        match self.sockets.get(channel) {
248            Some(s) => {
249                let filters: Vec<can_filter> = filters
250                    .iter()
251                    .map(|&f| can_filter {
252                        can_id: f.can_id,
253                        can_mask: f.can_mask,
254                    })
255                    .collect();
256                set_socket_option_mult(s.as_raw_fd(), SOL_CAN_RAW, CAN_RAW_FILTER, &filters)
257                    .map_err(|e| CanError::OperationError(e.to_string()))
258            }
259            None => Err(CanError::channel_not_opened(channel)),
260        }
261    }
262
263    /// Disable reception of CAN frames.
264    ///
265    /// Sets a completely empty filter; disabling all CAN frame reception.
266    pub fn set_filter_drop_all(&self, channel: &str) -> Result<(), CanError> {
267        match self.sockets.get(channel) {
268            Some(s) => {
269                let filters: &[CanFilter] = &[];
270                set_socket_option_mult(s.as_raw_fd(), SOL_CAN_RAW, CAN_RAW_FILTER, filters)
271                    .map_err(|e| CanError::OperationError(e.to_string()))
272            }
273            None => Err(CanError::channel_not_opened(channel)),
274        }
275    }
276
277    /// Accept all frames, disabling any kind of filtering.
278    ///
279    /// Replace the current filter with one containing a single rule that
280    /// accepts all CAN frames.
281    #[inline(always)]
282    pub fn set_filter_accept_all(&self, channel: &str) -> Result<(), CanError> {
283        self.set_filters(channel, &[CanFilter::default()])
284    }
285
286    /// Sets the error mask on the socket.
287    ///
288    /// By default (`ERR_MASK_NONE`) no error conditions are reported as
289    /// special error frames by the socket. Enabling error conditions by
290    /// setting `ERR_MASK_ALL` or another non-empty error mask causes the
291    /// socket to receive notification about the specified conditions.
292    pub fn set_error_filter(&self, channel: &str, mask: u32) -> Result<(), CanError> {
293        match self.sockets.get(channel) {
294            Some(s) => set_socket_option(s.as_raw_fd(), SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &mask)
295                .map_err(|e| CanError::OperationError(e.to_string())),
296            None => Err(CanError::channel_not_opened(channel)),
297        }
298    }
299
300    /// Sets the error mask on the socket to reject all errors.
301    #[inline(always)]
302    pub fn set_error_filter_drop_all(&self, channel: &str) -> Result<(), CanError> {
303        self.set_error_filter(channel, 0)
304    }
305
306    /// Sets the error mask on the socket to accept all errors.
307    #[inline(always)]
308    pub fn set_error_filter_accept_all(&self, channel: &str) -> Result<(), CanError> {
309        self.set_error_filter(channel, ERR_MASK)
310    }
311
312    /// Enable or disable loopback.
313    ///
314    /// By default, loopback is enabled, causing other applications that open
315    /// the same CAN bus to see frames emitted by different applications on
316    /// the same system.
317    pub fn set_loopback(&self, channel: &str, enabled: bool) -> Result<(), CanError> {
318        match self.sockets.get(channel) {
319            Some(s) => {
320                let loopback = c_int::from(enabled);
321                set_socket_option(s.as_raw_fd(), SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback)
322                    .map_err(|e| CanError::OperationError(e.to_string()))
323            }
324            None => Err(CanError::channel_not_opened(channel)),
325        }
326    }
327
328    /// Enable or disable receiving of own frames.
329    ///
330    /// When loopback is enabled, this settings controls if CAN frames sent
331    /// are received back immediately by sender. Default is off.
332    pub fn set_recv_own_msgs(&self, channel: &str, enabled: bool) -> Result<(), CanError> {
333        match self.sockets.get(channel) {
334            Some(s) => {
335                let recv_own_msgs = c_int::from(enabled);
336                set_socket_option(
337                    s.as_raw_fd(),
338                    SOL_CAN_RAW,
339                    CAN_RAW_RECV_OWN_MSGS,
340                    &recv_own_msgs,
341                )
342                .map_err(|e| CanError::OperationError(e.to_string()))
343            }
344            None => Err(CanError::channel_not_opened(channel)),
345        }
346    }
347
348    /// Enable or disable join filters.
349    ///
350    /// By default a frame is accepted if it matches any of the filters set
351    /// with `set_filters`. If join filters is enabled, a frame has to match
352    /// _all_ filters to be accepted.
353    pub fn set_join_filters(&self, channel: &str, enabled: bool) -> Result<(), CanError> {
354        match self.sockets.get(channel) {
355            Some(s) => {
356                let join_filters = c_int::from(enabled);
357                set_socket_option(
358                    s.as_raw_fd(),
359                    SOL_CAN_RAW,
360                    CAN_RAW_JOIN_FILTERS,
361                    &join_filters,
362                )
363                .map_err(|e| CanError::OperationError(e.to_string()))
364            }
365            None => Err(CanError::channel_not_opened(channel)),
366        }
367    }
368}