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 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 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 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 pub fn set_nonblocking(&self, channel: &str, nonblocking: bool) -> Result<(), CanError> {
172 match self.sockets.get(channel) {
173 Some(s) => {
174 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 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 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 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 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 #[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 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 #[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 #[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 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 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 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}