Skip to main content

can_hal_socketcan/
channel.rs

1use std::io;
2use std::time::{Duration, Instant};
3
4use socketcan::frame::CanAnyFrame;
5use socketcan::{CanFdSocket, Socket, SocketOptions};
6
7use can_hal::channel::{Receive, ReceiveFd, Transmit, TransmitFd};
8use can_hal::filter::{Filter, Filterable};
9use can_hal::frame::{CanFdFrame, CanFrame, Frame, Timestamped};
10
11use crate::convert;
12use crate::error::SocketCanError;
13
14/// A CAN channel backed by a Linux SocketCAN FD socket.
15///
16/// Implements `Transmit`, `Receive`, `TransmitFd`, `ReceiveFd`, and `Filterable`.
17///
18/// Created via [`SocketCanDriver`](crate::SocketCanDriver) or
19/// [`SocketCanChannel::open`].
20pub struct SocketCanChannel {
21    socket: CanFdSocket,
22    nonblocking: bool,
23}
24
25impl SocketCanChannel {
26    /// Open a channel on the named interface (e.g., `"vcan0"`, `"can0"`).
27    pub fn open(ifname: &str) -> Result<Self, SocketCanError> {
28        let socket = CanFdSocket::open(ifname)?;
29        Ok(Self {
30            socket,
31            nonblocking: false,
32        })
33    }
34
35    /// Open a channel by kernel interface index.
36    pub fn open_iface(ifindex: u32) -> Result<Self, SocketCanError> {
37        let socket = CanFdSocket::open_iface(ifindex)?;
38        Ok(Self {
39            socket,
40            nonblocking: false,
41        })
42    }
43
44    fn ensure_blocking(&mut self) -> Result<(), SocketCanError> {
45        if self.nonblocking {
46            self.socket.set_nonblocking(false)?;
47            self.nonblocking = false;
48        }
49        Ok(())
50    }
51
52    fn ensure_nonblocking(&mut self) -> Result<(), SocketCanError> {
53        if !self.nonblocking {
54            self.socket.set_nonblocking(true)?;
55            self.nonblocking = true;
56        }
57        Ok(())
58    }
59}
60
61impl Transmit for SocketCanChannel {
62    type Error = SocketCanError;
63
64    fn transmit(&mut self, frame: &CanFrame) -> Result<(), Self::Error> {
65        let sc_frame = convert::to_socketcan_data_frame(frame)?;
66        self.socket.write_frame(&sc_frame)?;
67        Ok(())
68    }
69}
70
71impl Receive for SocketCanChannel {
72    type Error = SocketCanError;
73    type Timestamp = Instant;
74
75    fn receive(&mut self) -> Result<Timestamped<CanFrame, Instant>, Self::Error> {
76        self.ensure_blocking()?;
77        loop {
78            let any_frame = self.socket.read_frame()?;
79            let now = Instant::now();
80            if let CanAnyFrame::Normal(data_frame) = any_frame {
81                let frame = convert::from_socketcan_data_frame(&data_frame)?;
82                return Ok(Timestamped::new(frame, now));
83            }
84            // Skip FD, remote, and error frames — caller wants classic only.
85        }
86    }
87
88    fn try_receive(&mut self) -> Result<Option<Timestamped<CanFrame, Instant>>, Self::Error> {
89        self.ensure_nonblocking()?;
90        loop {
91            match self.socket.read_frame() {
92                Ok(CanAnyFrame::Normal(data_frame)) => {
93                    let now = Instant::now();
94                    let frame = convert::from_socketcan_data_frame(&data_frame)?;
95                    return Ok(Some(Timestamped::new(frame, now)));
96                }
97                Ok(_) => continue, // skip FD/remote/error frames, drain queue
98                Err(e) if e.kind() == io::ErrorKind::WouldBlock => return Ok(None),
99                Err(e) => return Err(SocketCanError::Io(e)),
100            }
101        }
102    }
103
104    fn receive_timeout(
105        &mut self,
106        timeout: Duration,
107    ) -> Result<Option<Timestamped<CanFrame, Instant>>, Self::Error> {
108        self.ensure_blocking()?;
109        self.socket.set_read_timeout(timeout)?;
110        let deadline = Instant::now() + timeout;
111        let result = loop {
112            match self.socket.read_frame() {
113                Ok(CanAnyFrame::Normal(data_frame)) => {
114                    let now = Instant::now();
115                    break convert::from_socketcan_data_frame(&data_frame)
116                        .map(|f| Some(Timestamped::new(f, now)));
117                }
118                Ok(_) => {
119                    // Skip non-classic frames. Update remaining timeout.
120                    let now = Instant::now();
121                    if now >= deadline {
122                        break Ok(None);
123                    }
124                    let _ = self.socket.set_read_timeout(deadline - now);
125                    continue;
126                }
127                Err(e)
128                    if e.kind() == io::ErrorKind::WouldBlock
129                        || e.kind() == io::ErrorKind::TimedOut =>
130                {
131                    break Ok(None);
132                }
133                Err(e) => break Err(SocketCanError::Io(e)),
134            }
135        };
136        // Restore to no timeout (infinite blocking).
137        let _ = self.socket.set_read_timeout(None);
138        result
139    }
140}
141
142impl TransmitFd for SocketCanChannel {
143    type Error = SocketCanError;
144
145    fn transmit_fd(&mut self, frame: &CanFdFrame) -> Result<(), Self::Error> {
146        let sc_frame = convert::to_socketcan_fd_frame(frame)?;
147        self.socket.write_frame(&sc_frame)?;
148        Ok(())
149    }
150}
151
152impl ReceiveFd for SocketCanChannel {
153    type Error = SocketCanError;
154    type Timestamp = Instant;
155
156    fn receive_fd(&mut self) -> Result<Timestamped<Frame, Instant>, Self::Error> {
157        self.ensure_blocking()?;
158        loop {
159            let any_frame = self.socket.read_frame()?;
160            let now = Instant::now();
161            match convert::from_socketcan_any_frame(any_frame) {
162                Ok(frame) => return Ok(Timestamped::new(frame, now)),
163                Err(_) => continue, // Skip remote/error frames.
164            }
165        }
166    }
167
168    fn try_receive_fd(&mut self) -> Result<Option<Timestamped<Frame, Instant>>, Self::Error> {
169        self.ensure_nonblocking()?;
170        match self.socket.read_frame() {
171            Ok(any_frame) => {
172                let now = Instant::now();
173                match convert::from_socketcan_any_frame(any_frame) {
174                    Ok(frame) => Ok(Some(Timestamped::new(frame, now))),
175                    Err(_) => Ok(None),
176                }
177            }
178            Err(e) if e.kind() == io::ErrorKind::WouldBlock => Ok(None),
179            Err(e) => Err(SocketCanError::Io(e)),
180        }
181    }
182
183    fn receive_fd_timeout(
184        &mut self,
185        timeout: Duration,
186    ) -> Result<Option<Timestamped<Frame, Instant>>, Self::Error> {
187        self.ensure_blocking()?;
188        self.socket.set_read_timeout(timeout)?;
189        let deadline = Instant::now() + timeout;
190        let result = loop {
191            match self.socket.read_frame() {
192                Ok(any_frame) => {
193                    let now = Instant::now();
194                    match convert::from_socketcan_any_frame(any_frame) {
195                        Ok(frame) => break Ok(Some(Timestamped::new(frame, now))),
196                        Err(_) => {
197                            // Skip remote/error frames. Update remaining timeout.
198                            if now >= deadline {
199                                break Ok(None);
200                            }
201                            let _ = self.socket.set_read_timeout(deadline - now);
202                            continue;
203                        }
204                    }
205                }
206                Err(e)
207                    if e.kind() == io::ErrorKind::WouldBlock
208                        || e.kind() == io::ErrorKind::TimedOut =>
209                {
210                    break Ok(None);
211                }
212                Err(e) => break Err(SocketCanError::Io(e)),
213            }
214        };
215        let _ = self.socket.set_read_timeout(None);
216        result
217    }
218}
219
220impl Filterable for SocketCanChannel {
221    type Error = SocketCanError;
222
223    fn set_filters(&mut self, filters: &[Filter]) -> Result<(), Self::Error> {
224        let sc_filters: Vec<_> = filters.iter().map(convert::to_socketcan_filter).collect();
225        self.socket.set_filters(&sc_filters)?;
226        Ok(())
227    }
228
229    fn clear_filters(&mut self) -> Result<(), Self::Error> {
230        self.socket.set_filter_accept_all()?;
231        Ok(())
232    }
233}