socketcan_rs/
lib.rs

1mod constants;
2pub use constants::*;
3mod frame;
4pub use frame::*;
5mod socket;
6pub use socket::*;
7
8use std::{collections::HashMap, io, sync::Arc, os::{fd::{AsRawFd, BorrowedFd, FromRawFd, OwnedFd}, raw::{c_int, c_void}}, time::{Instant, Duration}};
9use libc::{can_filter, can_frame, canfd_frame, canxl_frame, fcntl, read, CAN_RAW_ERR_FILTER, CAN_RAW_FILTER, CAN_RAW_JOIN_FILTERS, CAN_RAW_LOOPBACK, CAN_RAW_RECV_OWN_MSGS, EINPROGRESS, F_GETFL, F_SETFL, O_NONBLOCK, SOL_CAN_RAW, SOL_SOCKET, SO_RCVTIMEO, SO_SNDTIMEO};
10use rs_can::{CanDevice, CanError, CanFilter, CanDirect, CanFrame, CanResult, ERR_MASK, DeviceBuilder};
11
12pub(crate) const FRAME_SIZE: usize = std::mem::size_of::<can_frame>();
13pub(crate) const FD_FRAME_SIZE: usize = std::mem::size_of::<canfd_frame>();
14pub(crate) const XL_FRAME_SIZE: usize = std::mem::size_of::<canxl_frame>();
15
16#[derive(Debug, Clone)]
17pub struct SocketCan {
18    sockets: Arc<HashMap<String, OwnedFd>>,
19}
20
21impl SocketCan {
22    pub fn new() -> Self {
23        Self { sockets: Default::default() }
24    }
25
26    pub fn init_channel(&mut self, channel: &str, canfd: bool) -> Result<(), CanError> {
27        let addr = CanAddr::from_iface(channel)
28            .map_err(|e| CanError::InitializeError(e.to_string()))?;
29
30        let _ = raw_open_socket(&addr)
31            .and_then(|fd| {
32                set_fd_mode(fd, canfd)
33            })
34            .and_then(|fd| {
35                Arc::get_mut(&mut self.sockets)
36                    .ok_or(io::Error::last_os_error())?
37                    .insert(channel.to_owned(), unsafe { OwnedFd::from_raw_fd(fd) });
38                // Rc::get_mut(&mut self.sockets)
39                //     .ok_or(io::Error::last_os_error())?
40                //     .insert(channel.to_owned(), unsafe { OwnedFd::from_raw_fd(fd) });
41                Ok(())
42            })
43            .map_err(|_| CanError::InitializeError("device open failed".into()));
44
45        Ok(())
46    }
47
48    pub fn read(&self, channel: &str) -> Result<CanMessage, CanError> {
49        match self.sockets.get(channel) {
50            Some(s) => {
51                let mut buffer = [0; XL_FRAME_SIZE];
52
53                let rd = unsafe { read(
54                    s.as_raw_fd(),
55                    &mut buffer as *mut _ as *mut c_void,
56                    XL_FRAME_SIZE
57                ) };
58                match rd as usize {
59                    FRAME_SIZE => {
60                        let frame = unsafe { *(&buffer as *const _ as *const can_frame) };
61                        let mut frame = CanMessage::from(CanAnyFrame::from(frame));
62                        frame.set_direct(CanDirect::Receive);
63                        Ok(frame)
64                    },
65                    FD_FRAME_SIZE => {
66                        let frame = unsafe { *(&buffer as *const _ as *const canfd_frame) };
67                        let mut frame = CanMessage::from(CanAnyFrame::from(frame));
68                        frame.set_direct(CanDirect::Receive);
69                        Ok(frame)
70                    },
71                    XL_FRAME_SIZE => {
72                        let frame = unsafe { *(&buffer as *const _ as *const canxl_frame) };
73                        let mut frame = CanMessage::from(CanAnyFrame::from(frame));
74                        frame.set_direct(CanDirect::Receive);
75                        Ok(frame)
76                    },
77                    _ => Err(CanError::OperationError(io::Error::last_os_error().to_string()))
78                }
79            },
80            None => Err(CanError::channel_not_opened(channel))
81        }
82    }
83
84    /// Blocking read a single can frame with timeout.
85    pub fn read_timeout(&self, channel: &str, timeout: Duration) -> Result<CanMessage, CanError> {
86        match self.sockets.get(channel) {
87            Some(s) => {
88                use nix::poll::{poll, PollFd, PollFlags};
89                let borrowed_fd = unsafe { BorrowedFd::borrow_raw(s.as_raw_fd()) };
90                let pollfd = PollFd::new(borrowed_fd, PollFlags::POLLIN);
91
92                match poll::<u16>(&mut [pollfd], timeout.as_millis() as u16)
93                    .map_err(|e| CanError::OperationError(e.to_string()))?
94                {
95                    0 => Err(CanError::channel_timeout(channel)),
96                    _ => self.read(channel),
97                }
98            },
99            None => Err(CanError::channel_not_opened(channel)),
100        }
101    }
102
103    pub fn write(&self, msg: CanMessage) -> Result<(), CanError> {
104        let channel = msg.channel();
105        match self.sockets.get(&channel) {
106            Some(s) => {
107                let frame: CanAnyFrame = msg.into();
108                match frame {
109                    CanAnyFrame::Normal(f) |
110                    CanAnyFrame::Remote(f) |
111                    CanAnyFrame::Error(f) => {
112                        raw_write_frame(s.as_raw_fd(), &f, frame.size())
113                            .map_err(|e| CanError::OtherError(e.to_string()))
114                    }
115                    CanAnyFrame::Fd(f) => {
116                        raw_write_frame(s.as_raw_fd(), &f, frame.size())
117                            .map_err(|e| CanError::OtherError(e.to_string()))
118                    },
119                    CanAnyFrame::Xl(f) => {
120                        raw_write_frame(s.as_raw_fd(), &f, frame.size())
121                            .map_err(|e| CanError::OtherError(e.to_string()))
122                    },
123                }
124            },
125            None => Err(CanError::channel_not_opened(channel))
126        }
127    }
128
129    /// Blocking write a single can frame, retrying until it gets sent successfully.
130    pub fn write_timeout(&self, msg: CanMessage, timeout: Duration) -> Result<(), CanError> {
131        let channel = msg.channel();
132        let frame: CanAnyFrame = msg.into();
133        let start = Instant::now();
134        while start.elapsed() < timeout {
135            match self.sockets.get(&channel) {
136                Some(s) => {
137                    if let Err(e) = match frame {
138                        CanAnyFrame::Normal(f) |
139                        CanAnyFrame::Remote(f) |
140                        CanAnyFrame::Error(f) => {
141                            raw_write_frame(s.as_raw_fd(), &f, frame.size())
142                        }
143                        CanAnyFrame::Fd(f) => {
144                            raw_write_frame(s.as_raw_fd(), &f, frame.size())
145                        },
146                        CanAnyFrame::Xl(f) => {
147                            raw_write_frame(s.as_raw_fd(), &f, frame.size())
148                        }
149                    } {
150                        match e.kind() {
151                            io::ErrorKind::WouldBlock => {},
152                            io::ErrorKind::Other =>
153                                if !matches!(e.raw_os_error(), Some(errno) if errno == EINPROGRESS) {
154                                    return Err(CanError::OperationError(e.to_string()));
155                                }
156                            _ => return Err(CanError::OperationError(e.to_string())),
157                        }
158                    }
159                    else {
160                        return Ok(());
161                    }
162                },
163                None => return Err(CanError::channel_not_opened(channel))
164            }
165        }
166
167        Err(CanError::channel_timeout(channel))
168    }
169
170    /// Change socket to non-blocking mode or back to blocking mode.
171    pub fn set_nonblocking(&self, channel: &str, nonblocking: bool) -> Result<(), CanError> {
172        match self.sockets.get(channel) {
173            Some(s) => {
174                // retrieve current flags
175                let oldfl = unsafe { fcntl(s.as_raw_fd(), F_GETFL) };
176
177                if oldfl == -1 {
178                    return Err(CanError::OperationError(io::Error::last_os_error().to_string()));
179                }
180
181                let newfl = if nonblocking {
182                    oldfl | O_NONBLOCK
183                } else {
184                    oldfl & !O_NONBLOCK
185                };
186
187                let ret = unsafe { fcntl(s.as_raw_fd(), F_SETFL, newfl) };
188
189                if ret != 0 {
190                    Err(CanError::OperationError(io::Error::last_os_error().to_string()))
191                }
192                else {
193                    Ok(())
194                }
195            },
196            None => Err(CanError::channel_not_opened(channel))
197        }
198    }
199
200    /// Sets the read timeout on the socket
201    ///
202    /// For convenience, the result value can be checked using
203    /// `ShouldRetry::should_retry` when a timeout is set.
204    pub fn set_read_timeout(&self, channel: &str, duration: Duration) -> Result<(), CanError> {
205        match self.sockets.get(channel) {
206            Some(s) => {
207                set_socket_option(
208                    s.as_raw_fd(),
209                    SOL_SOCKET,
210                    SO_RCVTIMEO,
211                    &c_timeval_new(duration),
212                )
213                    .map_err(|e| CanError::OperationError(e.to_string()))
214            },
215            None => Err(CanError::channel_not_opened(channel))
216        }
217    }
218
219    /// Sets the write timeout on the socket
220    pub fn set_write_timeout(&self, channel: &str, duration: Duration) -> Result<(), CanError> {
221        match self.sockets.get(channel) {
222            Some(s) => {
223                set_socket_option(
224                    s.as_raw_fd(),
225                    SOL_SOCKET,
226                    SO_SNDTIMEO,
227                    &c_timeval_new(duration),
228                )
229                    .map_err(|e| CanError::OperationError(e.to_string()))
230            },
231            None => Err(CanError::channel_not_opened(channel))
232        }
233    }
234}
235
236impl SocketCan {
237
238    /// Sets CAN ID filters on the socket.
239    ///
240    /// CAN packages received by SocketCAN are matched against these filters,
241    /// only matching packets are returned by the interface.
242    ///
243    /// See `CanFilter` for details on how filtering works. By default, all
244    /// single filter matching all incoming frames is installed.
245    pub fn set_filters(&self, channel: &str, filters: &[CanFilter]) -> Result<(), CanError> {
246        match self.sockets.get(channel) {
247            Some(s) => {
248                let filters: Vec<can_filter> = filters.iter()
249                    .map(|&f| {
250                        can_filter {
251                            can_id: f.can_id,
252                            can_mask: f.can_mask,
253                        }
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::from((0, 0))])
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) => {
295                set_socket_option(s.as_raw_fd(), SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &mask)
296                    .map_err(|e| CanError::OperationError(e.to_string()))
297            }
298            None => Err(CanError::channel_not_opened(channel)),
299        }
300    }
301
302    /// Sets the error mask on the socket to reject all errors.
303    #[inline(always)]
304    pub fn set_error_filter_drop_all(&self, channel: &str) -> Result<(), CanError> {
305        self.set_error_filter(channel, 0)
306    }
307
308    /// Sets the error mask on the socket to accept all errors.
309    #[inline(always)]
310    pub fn set_error_filter_accept_all(&self, channel: &str) -> Result<(), CanError> {
311        self.set_error_filter(channel, ERR_MASK)
312    }
313
314    /// Enable or disable loopback.
315    ///
316    /// By default, loopback is enabled, causing other applications that open
317    /// the same CAN bus to see frames emitted by different applications on
318    /// the same system.
319    pub fn set_loopback(&self, channel: &str, enabled: bool) -> Result<(), CanError> {
320        match self.sockets.get(channel) {
321            Some(s) => {
322                let loopback = c_int::from(enabled);
323                set_socket_option(s.as_raw_fd(), SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback)
324                    .map_err(|e| CanError::OperationError(e.to_string()))
325            }
326            None => Err(CanError::channel_not_opened(channel)),
327        }
328    }
329
330    /// Enable or disable receiving of own frames.
331    ///
332    /// When loopback is enabled, this settings controls if CAN frames sent
333    /// are received back immediately by sender. Default is off.
334    pub fn set_recv_own_msgs(&self, channel: &str, enabled: bool) -> Result<(), CanError> {
335        match self.sockets.get(channel) {
336            Some(s) => {
337                let recv_own_msgs = c_int::from(enabled);
338                set_socket_option(
339                    s.as_raw_fd(),
340                    SOL_CAN_RAW,
341                    CAN_RAW_RECV_OWN_MSGS,
342                    &recv_own_msgs,
343                )
344                    .map_err(|e| CanError::OperationError(e.to_string()))
345            }
346            None => Err(CanError::channel_not_opened(channel)),
347        }
348    }
349
350    /// Enable or disable join filters.
351    ///
352    /// By default a frame is accepted if it matches any of the filters set
353    /// with `set_filters`. If join filters is enabled, a frame has to match
354    /// _all_ filters to be accepted.
355    pub fn set_join_filters(&self, channel: &str, enabled: bool) -> Result<(), CanError> {
356        match self.sockets.get(channel) {
357            Some(s) => {
358                let join_filters = c_int::from(enabled);
359                set_socket_option(
360                    s.as_raw_fd(),
361                    SOL_CAN_RAW,
362                    CAN_RAW_JOIN_FILTERS,
363                    &join_filters,
364                )
365                    .map_err(|e| CanError::OperationError(e.to_string()))
366            }
367            None => Err(CanError::channel_not_opened(channel)),
368        }
369    }
370}
371
372impl TryFrom<DeviceBuilder<String>> for SocketCan {
373    type Error = CanError;
374
375    fn try_from(builder: DeviceBuilder<String>) -> Result<Self, Self::Error> {
376        let mut device = SocketCan::new();
377        builder.channel_configs()
378            .iter()
379            .try_for_each(|(chl, cfg)| {
380                let canfd = cfg.get_other::<bool>(CANFD)?
381                    .unwrap_or_default();
382                device.init_channel(chl, canfd)?;
383
384                if let Some(filters) = cfg.get_other::<Vec<CanFilter>>(FILTERS)? {
385                    device.set_filters(chl, &filters)?;
386                }
387
388                if let Some(loopback) = cfg.get_other::<bool>(LOOPBACK)? {
389                    device.set_loopback(chl, loopback)?;
390                }
391
392                if let Some(recv_own_msg) = cfg.get_other::<bool>(RECV_OWN_MSG)? {
393                    device.set_recv_own_msgs(chl, recv_own_msg)?;
394                }
395
396                Ok(())
397            })?;
398
399        Ok(device)
400    }
401}
402
403impl CanDevice for SocketCan {
404    type Channel = String;
405    type Frame = CanMessage;
406
407    #[inline(always)]
408    fn opened_channels(&self) -> Vec<Self::Channel> {
409        self.sockets.iter()
410            .map(|(c, _)| c.clone())
411            .collect()
412    }
413
414    #[inline(always)]
415    fn transmit(&self, msg: Self::Frame, timeout: Option<u32>) -> CanResult<(), CanError> {
416        match timeout {
417            Some(timeout) => self.write_timeout(msg, Duration::from_millis(timeout as u64)),
418            None => self.write(msg),
419        }
420    }
421
422    #[inline(always)]
423    fn receive(&self, channel: Self::Channel, timeout: Option<u32>) -> CanResult<Vec<Self::Frame>, CanError> {
424        let timeout = timeout.unwrap_or(0);
425        let msg = self.read_timeout(&channel, Duration::from_millis(timeout as u64))?;
426        Ok(vec![msg, ])
427    }
428
429    #[inline(always)]
430    fn shutdown(&mut self) {
431        match Arc::get_mut(&mut self.sockets) {
432            Some(s) => s.clear(),
433            None => (),
434        }
435    }
436}