Skip to main content

embedded_can_socketcan/
linux.rs

1use core::time::Duration;
2use embedded_can_interface::{
3    BlockingControl, FilterConfig, IdMask, IdMaskFilter, RxFrameIo, TxFrameIo,
4};
5use socketcan::{
6    CanAnyFrame, CanFdSocket, CanFilter, CanFrame, CanSocket, Error as SocketcanError, IoResult,
7    Socket, SocketOptions,
8};
9use std::os::unix::io::{AsRawFd, RawFd};
10
11/// Classic CAN SocketCAN adapter implementing `embedded-can-interface` traits.
12#[derive(Debug)]
13pub struct SocketCan {
14    inner: CanSocket,
15    nonblocking: bool,
16}
17
18impl SocketCan {
19    /// Open a SocketCAN interface by name (e.g. `"can0"`).
20    pub fn open(iface: &str) -> Result<Self, SocketcanError> {
21        let inner = CanSocket::open(iface)?;
22        let nonblocking = inner.nonblocking().map_err(SocketcanError::from)?;
23        Ok(Self { inner, nonblocking })
24    }
25
26    /// Wrap an existing `socketcan::CanSocket`.
27    pub fn new(inner: CanSocket) -> Self {
28        let nonblocking = inner.nonblocking().ok().unwrap_or(false);
29        Self { inner, nonblocking }
30    }
31
32    /// Borrow the inner SocketCAN socket.
33    pub fn as_inner(&self) -> &CanSocket {
34        &self.inner
35    }
36
37    /// Mutably borrow the inner SocketCAN socket.
38    pub fn as_inner_mut(&mut self) -> &mut CanSocket {
39        &mut self.inner
40    }
41
42    /// Unwrap into the inner SocketCAN socket.
43    pub fn into_inner(self) -> CanSocket {
44        self.inner
45    }
46}
47
48impl AsRawFd for SocketCan {
49    fn as_raw_fd(&self) -> RawFd {
50        self.inner.as_raw_fd()
51    }
52}
53
54/// CAN-FD SocketCAN adapter implementing `embedded-can-interface` traits.
55#[derive(Debug)]
56pub struct SocketCanFd {
57    inner: CanFdSocket,
58    nonblocking: bool,
59}
60
61impl SocketCanFd {
62    /// Open a SocketCAN interface by name (e.g. `"can0"`).
63    pub fn open(iface: &str) -> Result<Self, SocketcanError> {
64        let inner = CanFdSocket::open(iface)?;
65        let nonblocking = inner.nonblocking().map_err(SocketcanError::from)?;
66        Ok(Self { inner, nonblocking })
67    }
68
69    /// Wrap an existing `socketcan::CanFdSocket`.
70    pub fn new(inner: CanFdSocket) -> Self {
71        let nonblocking = inner.nonblocking().ok().unwrap_or(false);
72        Self { inner, nonblocking }
73    }
74
75    /// Borrow the inner SocketCAN socket.
76    pub fn as_inner(&self) -> &CanFdSocket {
77        &self.inner
78    }
79
80    /// Mutably borrow the inner SocketCAN socket.
81    pub fn as_inner_mut(&mut self) -> &mut CanFdSocket {
82        &mut self.inner
83    }
84
85    /// Unwrap into the inner SocketCAN socket.
86    pub fn into_inner(self) -> CanFdSocket {
87        self.inner
88    }
89}
90
91impl AsRawFd for SocketCanFd {
92    fn as_raw_fd(&self) -> RawFd {
93        self.inner.as_raw_fd()
94    }
95}
96
97fn map_can_frame(frame: CanFrame) -> Result<CanFrame, SocketcanError> {
98    match frame {
99        CanFrame::Error(frame) => Err(frame.into_error().into()),
100        frame => Ok(frame),
101    }
102}
103
104fn map_any_frame(frame: CanAnyFrame) -> Result<CanAnyFrame, SocketcanError> {
105    match frame {
106        CanAnyFrame::Error(frame) => Err(frame.into_error().into()),
107        frame => Ok(frame),
108    }
109}
110
111fn with_nonblocking<S, T>(
112    socket: &mut S,
113    nonblocking: &mut bool,
114    f: impl FnOnce(&mut S) -> IoResult<T>,
115) -> Result<T, SocketcanError>
116where
117    S: Socket,
118{
119    if *nonblocking {
120        return f(socket).map_err(SocketcanError::from);
121    }
122
123    let was_nonblocking = socket.nonblocking()?;
124    if was_nonblocking {
125        *nonblocking = true;
126        return f(socket).map_err(SocketcanError::from);
127    }
128
129    socket.set_nonblocking(true)?;
130    let result = f(socket).map_err(SocketcanError::from);
131    socket.set_nonblocking(false).map_err(SocketcanError::from)?;
132    result
133}
134
135fn with_write_timeout<S, T>(
136    socket: &mut S,
137    timeout: Duration,
138    f: impl FnOnce(&mut S) -> IoResult<T>,
139) -> Result<T, SocketcanError>
140where
141    S: Socket,
142{
143    let prev = socket.write_timeout()?;
144    socket.set_write_timeout(Some(timeout))?;
145    let result = f(socket).map_err(SocketcanError::from);
146    let reset = socket.set_write_timeout(prev).map_err(SocketcanError::from);
147    match reset {
148        Ok(()) => result,
149        Err(err) => Err(err),
150    }
151}
152
153fn wait_for_readable(fd: RawFd) -> Result<(), SocketcanError> {
154    let mut fds = libc::pollfd {
155        fd,
156        events: libc::POLLIN,
157        revents: 0,
158    };
159
160    loop {
161        let res = unsafe { libc::poll(&mut fds, 1, -1) };
162        if res >= 0 {
163            return Ok(());
164        }
165
166        let err = std::io::Error::last_os_error();
167        if err.kind() == std::io::ErrorKind::Interrupted {
168            continue;
169        }
170        return Err(err.into());
171    }
172}
173
174fn to_socketcan_filter(f: &IdMaskFilter) -> Result<CanFilter, SocketcanError> {
175    // SocketCAN raw filters match `received_id & mask == filter_id & mask` where IDs include flag
176    // bits (EFF/RTR/ERR). Ensure we match the intended frame format by including EFF in the mask.
177    let (id_raw, mask_raw) = match (f.id, f.mask) {
178        (embedded_can_interface::Id::Standard(id), IdMask::Standard(mask)) => {
179            let can_id = u32::from(id.as_raw());
180            let can_mask = u32::from(mask) | libc::CAN_EFF_FLAG;
181            (can_id, can_mask)
182        }
183        (embedded_can_interface::Id::Extended(id), IdMask::Extended(mask)) => {
184            let can_id = id.as_raw() | libc::CAN_EFF_FLAG;
185            let can_mask = (mask & 0x1FFF_FFFF) | libc::CAN_EFF_FLAG;
186            (can_id, can_mask)
187        }
188        _ => {
189            return Err(std::io::Error::new(
190                std::io::ErrorKind::InvalidInput,
191                "id/mask width mismatch",
192            )
193            .into());
194        }
195    };
196    Ok(CanFilter::new(id_raw, mask_raw))
197}
198
199impl TxFrameIo for SocketCan {
200    type Frame = CanFrame;
201    type Error = SocketcanError;
202
203    fn send(&mut self, frame: &Self::Frame) -> Result<(), Self::Error> {
204        self.inner
205            .write_frame_insist(frame)
206            .map_err(SocketcanError::from)
207    }
208
209    fn try_send(&mut self, frame: &Self::Frame) -> Result<(), Self::Error> {
210        with_nonblocking(&mut self.inner, &mut self.nonblocking, |socket| {
211            socket.write_frame(frame)
212        })
213    }
214
215    fn send_timeout(&mut self, frame: &Self::Frame, timeout: Duration) -> Result<(), Self::Error> {
216        with_write_timeout(&mut self.inner, timeout, |socket| socket.write_frame(frame))
217    }
218}
219
220impl RxFrameIo for SocketCan {
221    type Frame = CanFrame;
222    type Error = SocketcanError;
223
224    fn recv(&mut self) -> Result<Self::Frame, Self::Error> {
225        let frame = self.inner.read_frame().map_err(SocketcanError::from)?;
226        map_can_frame(frame)
227    }
228
229    fn try_recv(&mut self) -> Result<Self::Frame, Self::Error> {
230        let frame = with_nonblocking(&mut self.inner, &mut self.nonblocking, |socket| {
231            socket.read_frame()
232        })?;
233        map_can_frame(frame)
234    }
235
236    fn recv_timeout(&mut self, timeout: Duration) -> Result<Self::Frame, Self::Error> {
237        let frame = self
238            .inner
239            .read_frame_timeout(timeout)
240            .map_err(SocketcanError::from)?;
241        map_can_frame(frame)
242    }
243
244    fn wait_not_empty(&mut self) -> Result<(), Self::Error> {
245        wait_for_readable(self.as_raw_fd())
246    }
247}
248
249impl BlockingControl for SocketCan {
250    type Error = SocketcanError;
251
252    fn set_nonblocking(&mut self, on: bool) -> Result<(), Self::Error> {
253        self.inner
254            .set_nonblocking(on)
255            .map_err(SocketcanError::from)?;
256        self.nonblocking = on;
257        Ok(())
258    }
259}
260
261impl FilterConfig for SocketCan {
262    type Error = SocketcanError;
263    type FiltersHandle<'a>
264        = ()
265    where
266        Self: 'a;
267
268    fn set_filters(&mut self, filters: &[IdMaskFilter]) -> Result<(), Self::Error> {
269        if filters.is_empty() {
270            // `embedded-can-interface` generally treats an empty list as “accept all”.
271            return self
272                .inner
273                .set_filter_accept_all()
274                .map_err(SocketcanError::from);
275        }
276        let mut out: Vec<CanFilter> = Vec::with_capacity(filters.len());
277        for f in filters {
278            out.push(to_socketcan_filter(f)?);
279        }
280        self.inner.set_filters(&out).map_err(SocketcanError::from)
281    }
282
283    fn modify_filters(&mut self) -> Self::FiltersHandle<'_> {
284        
285    }
286}
287
288impl TxFrameIo for SocketCanFd {
289    type Frame = CanAnyFrame;
290    type Error = SocketcanError;
291
292    fn send(&mut self, frame: &Self::Frame) -> Result<(), Self::Error> {
293        self.inner
294            .write_frame_insist(frame)
295            .map_err(SocketcanError::from)
296    }
297
298    fn try_send(&mut self, frame: &Self::Frame) -> Result<(), Self::Error> {
299        with_nonblocking(&mut self.inner, &mut self.nonblocking, |socket| {
300            socket.write_frame(frame)
301        })
302    }
303
304    fn send_timeout(&mut self, frame: &Self::Frame, timeout: Duration) -> Result<(), Self::Error> {
305        with_write_timeout(&mut self.inner, timeout, |socket| socket.write_frame(frame))
306    }
307}
308
309impl RxFrameIo for SocketCanFd {
310    type Frame = CanAnyFrame;
311    type Error = SocketcanError;
312
313    fn recv(&mut self) -> Result<Self::Frame, Self::Error> {
314        let frame = self.inner.read_frame().map_err(SocketcanError::from)?;
315        map_any_frame(frame)
316    }
317
318    fn try_recv(&mut self) -> Result<Self::Frame, Self::Error> {
319        let frame = with_nonblocking(&mut self.inner, &mut self.nonblocking, |socket| {
320            socket.read_frame()
321        })?;
322        map_any_frame(frame)
323    }
324
325    fn recv_timeout(&mut self, timeout: Duration) -> Result<Self::Frame, Self::Error> {
326        let frame = self
327            .inner
328            .read_frame_timeout(timeout)
329            .map_err(SocketcanError::from)?;
330        map_any_frame(frame)
331    }
332
333    fn wait_not_empty(&mut self) -> Result<(), Self::Error> {
334        wait_for_readable(self.as_raw_fd())
335    }
336}
337
338impl BlockingControl for SocketCanFd {
339    type Error = SocketcanError;
340
341    fn set_nonblocking(&mut self, on: bool) -> Result<(), Self::Error> {
342        self.inner
343            .set_nonblocking(on)
344            .map_err(SocketcanError::from)?;
345        self.nonblocking = on;
346        Ok(())
347    }
348}
349
350impl FilterConfig for SocketCanFd {
351    type Error = SocketcanError;
352    type FiltersHandle<'a>
353        = ()
354    where
355        Self: 'a;
356
357    fn set_filters(&mut self, filters: &[IdMaskFilter]) -> Result<(), Self::Error> {
358        if filters.is_empty() {
359            return self
360                .inner
361                .set_filter_accept_all()
362                .map_err(SocketcanError::from);
363        }
364        let mut out: Vec<CanFilter> = Vec::with_capacity(filters.len());
365        for f in filters {
366            out.push(to_socketcan_filter(f)?);
367        }
368        self.inner.set_filters(&out).map_err(SocketcanError::from)
369    }
370
371    fn modify_filters(&mut self) -> Self::FiltersHandle<'_> {
372        
373    }
374}
375
376#[cfg(feature = "tokio")]
377#[path = "tokio_impl.rs"]
378mod tokio_impl;
379
380#[cfg(feature = "tokio")]
381pub use tokio_impl::{TokioSocketCan, TokioSocketCanFd};