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#[derive(Debug)]
13pub struct SocketCan {
14 inner: CanSocket,
15 nonblocking: bool,
16}
17
18impl SocketCan {
19 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 pub fn new(inner: CanSocket) -> Self {
28 let nonblocking = inner.nonblocking().ok().unwrap_or(false);
29 Self { inner, nonblocking }
30 }
31
32 pub fn as_inner(&self) -> &CanSocket {
34 &self.inner
35 }
36
37 pub fn as_inner_mut(&mut self) -> &mut CanSocket {
39 &mut self.inner
40 }
41
42 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#[derive(Debug)]
56pub struct SocketCanFd {
57 inner: CanFdSocket,
58 nonblocking: bool,
59}
60
61impl SocketCanFd {
62 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 pub fn new(inner: CanFdSocket) -> Self {
71 let nonblocking = inner.nonblocking().ok().unwrap_or(false);
72 Self { inner, nonblocking }
73 }
74
75 pub fn as_inner(&self) -> &CanFdSocket {
77 &self.inner
78 }
79
80 pub fn as_inner_mut(&mut self) -> &mut CanFdSocket {
82 &mut self.inner
83 }
84
85 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 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 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};