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(_) => {} // 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                    self.socket.set_read_timeout(deadline - now).ok();
125                }
126                Err(e)
127                    if e.kind() == io::ErrorKind::WouldBlock
128                        || e.kind() == io::ErrorKind::TimedOut =>
129                {
130                    break Ok(None);
131                }
132                Err(e) => break Err(SocketCanError::Io(e)),
133            }
134        };
135        // Restore to no timeout (infinite blocking).
136        self.socket.set_read_timeout(None).ok();
137        result
138    }
139}
140
141impl TransmitFd for SocketCanChannel {
142    type Error = SocketCanError;
143
144    fn transmit_fd(&mut self, frame: &CanFdFrame) -> Result<(), Self::Error> {
145        let sc_frame = convert::to_socketcan_fd_frame(frame)?;
146        self.socket.write_frame(&sc_frame)?;
147        Ok(())
148    }
149}
150
151impl ReceiveFd for SocketCanChannel {
152    type Error = SocketCanError;
153    type Timestamp = Instant;
154
155    fn receive_fd(&mut self) -> Result<Timestamped<Frame, Instant>, Self::Error> {
156        self.ensure_blocking()?;
157        loop {
158            let any_frame = self.socket.read_frame()?;
159            let now = Instant::now();
160            if let Ok(frame) = convert::from_socketcan_any_frame(any_frame) {
161                return Ok(Timestamped::new(frame, now));
162            }
163            // Skip remote/error frames.
164        }
165    }
166
167    fn try_receive_fd(&mut self) -> Result<Option<Timestamped<Frame, Instant>>, Self::Error> {
168        self.ensure_nonblocking()?;
169        match self.socket.read_frame() {
170            Ok(any_frame) => {
171                let now = Instant::now();
172                Ok(convert::from_socketcan_any_frame(any_frame)
173                    .ok()
174                    .map(|frame| Timestamped::new(frame, now)))
175            }
176            Err(e) if e.kind() == io::ErrorKind::WouldBlock => Ok(None),
177            Err(e) => Err(SocketCanError::Io(e)),
178        }
179    }
180
181    fn receive_fd_timeout(
182        &mut self,
183        timeout: Duration,
184    ) -> Result<Option<Timestamped<Frame, Instant>>, Self::Error> {
185        self.ensure_blocking()?;
186        self.socket.set_read_timeout(timeout)?;
187        let deadline = Instant::now() + timeout;
188        let result = loop {
189            match self.socket.read_frame() {
190                Ok(any_frame) => {
191                    let now = Instant::now();
192                    if let Ok(frame) = convert::from_socketcan_any_frame(any_frame) {
193                        break Ok(Some(Timestamped::new(frame, now)));
194                    }
195                    // Skip remote/error frames. Update remaining timeout.
196                    if now >= deadline {
197                        break Ok(None);
198                    }
199                    self.socket.set_read_timeout(deadline - now).ok();
200                }
201                Err(e)
202                    if e.kind() == io::ErrorKind::WouldBlock
203                        || e.kind() == io::ErrorKind::TimedOut =>
204                {
205                    break Ok(None);
206                }
207                Err(e) => break Err(SocketCanError::Io(e)),
208            }
209        };
210        self.socket.set_read_timeout(None).ok();
211        result
212    }
213}
214
215impl Filterable for SocketCanChannel {
216    type Error = SocketCanError;
217
218    fn set_filters(&mut self, filters: &[Filter]) -> Result<(), Self::Error> {
219        // An empty filter set means "no constraint, accept everything",
220        // matching the trait contract. Passing an empty vector to socketcan's
221        // set_filters() would otherwise block all frames.
222        if filters.is_empty() {
223            return self.clear_filters();
224        }
225        let sc_filters: Vec<_> = filters.iter().map(convert::to_socketcan_filter).collect();
226        self.socket.set_filters(&sc_filters)?;
227        Ok(())
228    }
229
230    fn clear_filters(&mut self) -> Result<(), Self::Error> {
231        self.socket.set_filter_accept_all()?;
232        Ok(())
233    }
234}