Skip to main content

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, SocketCanFrame,
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::{CanDirection, CanError, CanFilter, CanFrame, CanResult, 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) -> CanResult<()> {
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) -> CanResult<SocketCanFrame> {
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 = SocketCanFrame::try_from(CanAnyFrame::from(frame))?;
74                        frame.set_direction(CanDirection::Receive);
75                        Ok(frame)
76                    }
77                    FD_FRAME_SIZE => {
78                        let frame = unsafe { *(&buffer as *const _ as *const canfd_frame) };
79                        let mut frame = SocketCanFrame::try_from(CanAnyFrame::from(frame))?;
80                        frame.set_direction(CanDirection::Receive);
81                        Ok(frame)
82                    }
83                    XL_FRAME_SIZE => {
84                        let frame = unsafe { *(&buffer as *const _ as *const canxl_frame) };
85                        let mut frame = SocketCanFrame::try_from(CanAnyFrame::from(frame))?;
86                        frame.set_direction(CanDirection::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) -> CanResult<SocketCanFrame> {
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: SocketCanFrame) -> CanResult<()> {
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: SocketCanFrame, timeout: Duration) -> CanResult<()> {
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) -> CanResult<()> {
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) -> CanResult<()> {
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) -> CanResult<()> {
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]) -> CanResult<()> {
247        match self.sockets.get(channel) {
248            Some(s) => {
249                let filters: Vec<can_filter> = filters
250                    .iter()
251                    .map(|&f| match f {
252                        CanFilter::Standard { id, mask } => can_filter {
253                            can_id: id.as_raw() as u32,
254                            can_mask: mask as u32,
255                        },
256                        CanFilter::Extended { id, mask } => can_filter {
257                            can_id: id.as_raw(),
258                            can_mask: mask,
259                        },
260                    })
261                    .collect();
262                set_socket_option_mult(s.as_raw_fd(), SOL_CAN_RAW, CAN_RAW_FILTER, &filters)
263                    .map_err(|e| CanError::OperationError(e.to_string()))
264            }
265            None => Err(CanError::channel_not_opened(channel)),
266        }
267    }
268
269    /// Disable reception of CAN frames.
270    ///
271    /// Sets a completely empty filter; disabling all CAN frame reception.
272    pub fn set_filter_drop_all(&self, channel: &str) -> CanResult<()> {
273        match self.sockets.get(channel) {
274            Some(s) => {
275                let filters: &[CanFilter] = &[];
276                set_socket_option_mult(s.as_raw_fd(), SOL_CAN_RAW, CAN_RAW_FILTER, filters)
277                    .map_err(|e| CanError::OperationError(e.to_string()))
278            }
279            None => Err(CanError::channel_not_opened(channel)),
280        }
281    }
282
283    /// Accept all frames, disabling any kind of filtering.
284    ///
285    /// Replace the current filter with one containing a single rule that
286    /// accepts all CAN frames.
287    #[inline(always)]
288    pub fn set_filter_accept_all(&self, channel: &str) -> CanResult<()> {
289        self.set_filters(channel, &[CanFilter::default()])
290    }
291
292    /// Sets the error mask on the socket.
293    ///
294    /// By default (`ERR_MASK_NONE`) no error conditions are reported as
295    /// special error frames by the socket. Enabling error conditions by
296    /// setting `ERR_MASK_ALL` or another non-empty error mask causes the
297    /// socket to receive notification about the specified conditions.
298    pub fn set_error_filter(&self, channel: &str, mask: u32) -> CanResult<()> {
299        match self.sockets.get(channel) {
300            Some(s) => set_socket_option(s.as_raw_fd(), SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &mask)
301                .map_err(|e| CanError::OperationError(e.to_string())),
302            None => Err(CanError::channel_not_opened(channel)),
303        }
304    }
305
306    /// Sets the error mask on the socket to reject all errors.
307    #[inline(always)]
308    pub fn set_error_filter_drop_all(&self, channel: &str) -> CanResult<()> {
309        self.set_error_filter(channel, 0)
310    }
311
312    /// Sets the error mask on the socket to accept all errors.
313    #[inline(always)]
314    pub fn set_error_filter_accept_all(&self, channel: &str) -> CanResult<()> {
315        self.set_error_filter(channel, ERR_MASK)
316    }
317
318    /// Enable or disable loopback.
319    ///
320    /// By default, loopback is enabled, causing other applications that open
321    /// the same CAN bus to see frames emitted by different applications on
322    /// the same system.
323    pub fn set_loopback(&self, channel: &str, enabled: bool) -> CanResult<()> {
324        match self.sockets.get(channel) {
325            Some(s) => {
326                let loopback = c_int::from(enabled);
327                set_socket_option(s.as_raw_fd(), SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback)
328                    .map_err(|e| CanError::OperationError(e.to_string()))
329            }
330            None => Err(CanError::channel_not_opened(channel)),
331        }
332    }
333
334    /// Enable or disable receiving of own frames.
335    ///
336    /// When loopback is enabled, this settings controls if CAN frames sent
337    /// are received back immediately by sender. Default is off.
338    pub fn set_recv_own_msgs(&self, channel: &str, enabled: bool) -> CanResult<()> {
339        match self.sockets.get(channel) {
340            Some(s) => {
341                let recv_own_msgs = c_int::from(enabled);
342                set_socket_option(
343                    s.as_raw_fd(),
344                    SOL_CAN_RAW,
345                    CAN_RAW_RECV_OWN_MSGS,
346                    &recv_own_msgs,
347                )
348                .map_err(|e| CanError::OperationError(e.to_string()))
349            }
350            None => Err(CanError::channel_not_opened(channel)),
351        }
352    }
353
354    /// Enable or disable join filters.
355    ///
356    /// By default a frame is accepted if it matches any of the filters set
357    /// with `set_filters`. If join filters is enabled, a frame has to match
358    /// _all_ filters to be accepted.
359    pub fn set_join_filters(&self, channel: &str, enabled: bool) -> CanResult<()> {
360        match self.sockets.get(channel) {
361            Some(s) => {
362                let join_filters = c_int::from(enabled);
363                set_socket_option(
364                    s.as_raw_fd(),
365                    SOL_CAN_RAW,
366                    CAN_RAW_JOIN_FILTERS,
367                    &join_filters,
368                )
369                .map_err(|e| CanError::OperationError(e.to_string()))
370            }
371            None => Err(CanError::channel_not_opened(channel)),
372        }
373    }
374}