1use std::{collections::HashMap, io, sync::Arc, os::{fd::{AsRawFd, BorrowedFd, FromRawFd, OwnedFd}, raw::{c_int, c_void}}, time::{Instant, Duration}};
2use 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};
3use rs_can::{CanError, CanFilter, CanDirect, CanFrame, ERR_MASK};
4use crate::{c_timeval_new, raw_open_socket, raw_write_frame, set_fd_mode, set_socket_option, set_socket_option_mult, CanAddr, CanAnyFrame, CanMessage};
5
6pub(crate) const FRAME_SIZE: usize = std::mem::size_of::<can_frame>();
7pub(crate) const FD_FRAME_SIZE: usize = std::mem::size_of::<canfd_frame>();
8pub(crate) const XL_FRAME_SIZE: usize = std::mem::size_of::<canxl_frame>();
9
10#[derive(Debug, Clone)]
11pub struct SocketCan {
12 pub(crate) sockets: Arc<HashMap<String, OwnedFd>>,
13}
14
15impl SocketCan {
16 pub fn new() -> Self {
17 Self { sockets: Default::default() }
18 }
19
20 pub fn init_channel(&mut self, channel: &str, canfd: bool) -> Result<(), CanError> {
21 let addr = CanAddr::from_iface(channel)
22 .map_err(|e| CanError::InitializeError(e.to_string()))?;
23
24 let _ = raw_open_socket(&addr)
25 .and_then(|fd| {
26 set_fd_mode(fd, canfd)
27 })
28 .and_then(|fd| {
29 Arc::get_mut(&mut self.sockets)
30 .ok_or(io::Error::last_os_error())?
31 .insert(channel.to_owned(), unsafe { OwnedFd::from_raw_fd(fd) });
32 Ok(())
36 })
37 .map_err(|_| CanError::InitializeError("device open failed".into()));
38
39 Ok(())
40 }
41
42 pub fn read(&self, channel: &str) -> Result<CanMessage, CanError> {
43 match self.sockets.get(channel) {
44 Some(s) => {
45 let mut buffer = [0; XL_FRAME_SIZE];
46
47 let rd = unsafe { read(
48 s.as_raw_fd(),
49 &mut buffer as *mut _ as *mut c_void,
50 XL_FRAME_SIZE
51 ) };
52 match rd as usize {
53 FRAME_SIZE => {
54 let frame = unsafe { *(&buffer as *const _ as *const can_frame) };
55 let mut frame = CanMessage::from(CanAnyFrame::from(frame));
56 frame.set_direct(CanDirect::Receive);
57 Ok(frame)
58 },
59 FD_FRAME_SIZE => {
60 let frame = unsafe { *(&buffer as *const _ as *const canfd_frame) };
61 let mut frame = CanMessage::from(CanAnyFrame::from(frame));
62 frame.set_direct(CanDirect::Receive);
63 Ok(frame)
64 },
65 XL_FRAME_SIZE => {
66 let frame = unsafe { *(&buffer as *const _ as *const canxl_frame) };
67 let mut frame = CanMessage::from(CanAnyFrame::from(frame));
68 frame.set_direct(CanDirect::Receive);
69 Ok(frame)
70 },
71 _ => Err(CanError::OperationError(io::Error::last_os_error().to_string()))
72 }
73 },
74 None => Err(CanError::channel_not_opened(channel))
75 }
76 }
77
78 pub fn read_timeout(&self, channel: &str, timeout: Duration) -> Result<CanMessage, CanError> {
80 match self.sockets.get(channel) {
81 Some(s) => {
82 use nix::poll::{poll, PollFd, PollFlags};
83 let borrowed_fd = unsafe { BorrowedFd::borrow_raw(s.as_raw_fd()) };
84 let pollfd = PollFd::new(borrowed_fd, PollFlags::POLLIN);
85
86 match poll::<u16>(&mut [pollfd], timeout.as_millis() as u16)
87 .map_err(|e| CanError::OperationError(e.to_string()))?
88 {
89 0 => Err(CanError::channel_timeout(channel)),
90 _ => self.read(channel),
91 }
92 },
93 None => Err(CanError::channel_not_opened(channel)),
94 }
95 }
96
97 pub fn write(&self, msg: CanMessage) -> Result<(), CanError> {
98 let channel = msg.channel();
99 match self.sockets.get(&channel) {
100 Some(s) => {
101 let frame: CanAnyFrame = msg.into();
102 match frame {
103 CanAnyFrame::Normal(f) |
104 CanAnyFrame::Remote(f) |
105 CanAnyFrame::Error(f) => {
106 raw_write_frame(s.as_raw_fd(), &f, frame.size())
107 .map_err(|e| CanError::OtherError(e.to_string()))
108 }
109 CanAnyFrame::Fd(f) => {
110 raw_write_frame(s.as_raw_fd(), &f, frame.size())
111 .map_err(|e| CanError::OtherError(e.to_string()))
112 },
113 CanAnyFrame::Xl(f) => {
114 raw_write_frame(s.as_raw_fd(), &f, frame.size())
115 .map_err(|e| CanError::OtherError(e.to_string()))
116 },
117 }
118 },
119 None => Err(CanError::channel_not_opened(channel))
120 }
121 }
122
123 pub fn write_timeout(&self, msg: CanMessage, timeout: Duration) -> Result<(), CanError> {
125 let channel = msg.channel();
126 let frame: CanAnyFrame = msg.into();
127 let start = Instant::now();
128 while start.elapsed() < timeout {
129 match self.sockets.get(&channel) {
130 Some(s) => {
131 if let Err(e) = match frame {
132 CanAnyFrame::Normal(f) |
133 CanAnyFrame::Remote(f) |
134 CanAnyFrame::Error(f) => {
135 raw_write_frame(s.as_raw_fd(), &f, frame.size())
136 }
137 CanAnyFrame::Fd(f) => {
138 raw_write_frame(s.as_raw_fd(), &f, frame.size())
139 },
140 CanAnyFrame::Xl(f) => {
141 raw_write_frame(s.as_raw_fd(), &f, frame.size())
142 }
143 } {
144 match e.kind() {
145 io::ErrorKind::WouldBlock => {},
146 io::ErrorKind::Other =>
147 if !matches!(e.raw_os_error(), Some(errno) if errno == EINPROGRESS) {
148 return Err(CanError::OperationError(e.to_string()));
149 }
150 _ => return Err(CanError::OperationError(e.to_string())),
151 }
152 }
153 else {
154 return Ok(());
155 }
156 },
157 None => return Err(CanError::channel_not_opened(channel))
158 }
159 }
160
161 Err(CanError::channel_timeout(channel))
162 }
163
164 pub fn set_nonblocking(&self, channel: &str, nonblocking: bool) -> Result<(), CanError> {
166 match self.sockets.get(channel) {
167 Some(s) => {
168 let oldfl = unsafe { fcntl(s.as_raw_fd(), F_GETFL) };
170
171 if oldfl == -1 {
172 return Err(CanError::OperationError(io::Error::last_os_error().to_string()));
173 }
174
175 let newfl = if nonblocking {
176 oldfl | O_NONBLOCK
177 } else {
178 oldfl & !O_NONBLOCK
179 };
180
181 let ret = unsafe { fcntl(s.as_raw_fd(), F_SETFL, newfl) };
182
183 if ret != 0 {
184 Err(CanError::OperationError(io::Error::last_os_error().to_string()))
185 }
186 else {
187 Ok(())
188 }
189 },
190 None => Err(CanError::channel_not_opened(channel))
191 }
192 }
193
194 pub fn set_read_timeout(&self, channel: &str, duration: Duration) -> Result<(), CanError> {
199 match self.sockets.get(channel) {
200 Some(s) => {
201 set_socket_option(
202 s.as_raw_fd(),
203 SOL_SOCKET,
204 SO_RCVTIMEO,
205 &c_timeval_new(duration),
206 )
207 .map_err(|e| CanError::OperationError(e.to_string()))
208 },
209 None => Err(CanError::channel_not_opened(channel))
210 }
211 }
212
213 pub fn set_write_timeout(&self, channel: &str, duration: Duration) -> Result<(), CanError> {
215 match self.sockets.get(channel) {
216 Some(s) => {
217 set_socket_option(
218 s.as_raw_fd(),
219 SOL_SOCKET,
220 SO_SNDTIMEO,
221 &c_timeval_new(duration),
222 )
223 .map_err(|e| CanError::OperationError(e.to_string()))
224 },
225 None => Err(CanError::channel_not_opened(channel))
226 }
227 }
228}
229
230impl SocketCan {
231
232 pub fn set_filters(&self, channel: &str, filters: &[CanFilter]) -> Result<(), CanError> {
240 match self.sockets.get(channel) {
241 Some(s) => {
242 let filters: Vec<can_filter> = filters.iter()
243 .map(|&f| {
244 can_filter {
245 can_id: f.can_id,
246 can_mask: f.can_mask,
247 }
248 })
249 .collect();
250 set_socket_option_mult(s.as_raw_fd(), SOL_CAN_RAW, CAN_RAW_FILTER, &filters)
251 .map_err(|e| CanError::OperationError(e.to_string()))
252 },
253 None => Err(CanError::channel_not_opened(channel)),
254 }
255 }
256
257 pub fn set_filter_drop_all(&self, channel: &str) -> Result<(), CanError> {
261 match self.sockets.get(channel) {
262 Some(s) => {
263 let filters: &[CanFilter] = &[];
264 set_socket_option_mult(s.as_raw_fd(), SOL_CAN_RAW, CAN_RAW_FILTER, filters)
265 .map_err(|e| CanError::OperationError(e.to_string()))
266 }
267 None => Err(CanError::channel_not_opened(channel)),
268 }
269 }
270
271 #[inline(always)]
276 pub fn set_filter_accept_all(&self, channel: &str) -> Result<(), CanError> {
277 self.set_filters(channel, &[CanFilter::from((0, 0))])
278 }
279
280 pub fn set_error_filter(&self, channel: &str, mask: u32) -> Result<(), CanError> {
287 match self.sockets.get(channel) {
288 Some(s) => {
289 set_socket_option(s.as_raw_fd(), SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &mask)
290 .map_err(|e| CanError::OperationError(e.to_string()))
291 }
292 None => Err(CanError::channel_not_opened(channel)),
293 }
294 }
295
296 #[inline(always)]
298 pub fn set_error_filter_drop_all(&self, channel: &str) -> Result<(), CanError> {
299 self.set_error_filter(channel, 0)
300 }
301
302 #[inline(always)]
304 pub fn set_error_filter_accept_all(&self, channel: &str) -> Result<(), CanError> {
305 self.set_error_filter(channel, ERR_MASK)
306 }
307
308 pub fn set_loopback(&self, channel: &str, enabled: bool) -> Result<(), CanError> {
314 match self.sockets.get(channel) {
315 Some(s) => {
316 let loopback = c_int::from(enabled);
317 set_socket_option(s.as_raw_fd(), SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback)
318 .map_err(|e| CanError::OperationError(e.to_string()))
319 }
320 None => Err(CanError::channel_not_opened(channel)),
321 }
322 }
323
324 pub fn set_recv_own_msgs(&self, channel: &str, enabled: bool) -> Result<(), CanError> {
329 match self.sockets.get(channel) {
330 Some(s) => {
331 let recv_own_msgs = c_int::from(enabled);
332 set_socket_option(
333 s.as_raw_fd(),
334 SOL_CAN_RAW,
335 CAN_RAW_RECV_OWN_MSGS,
336 &recv_own_msgs,
337 )
338 .map_err(|e| CanError::OperationError(e.to_string()))
339 }
340 None => Err(CanError::channel_not_opened(channel)),
341 }
342 }
343
344 pub fn set_join_filters(&self, channel: &str, enabled: bool) -> Result<(), CanError> {
350 match self.sockets.get(channel) {
351 Some(s) => {
352 let join_filters = c_int::from(enabled);
353 set_socket_option(
354 s.as_raw_fd(),
355 SOL_CAN_RAW,
356 CAN_RAW_JOIN_FILTERS,
357 &join_filters,
358 )
359 .map_err(|e| CanError::OperationError(e.to_string()))
360 }
361 None => Err(CanError::channel_not_opened(channel)),
362 }
363 }
364}