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