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, CanMessage,
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::{CanDirect, CanError, CanFilter, CanFrame, 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) -> Result<(), CanError> {
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) -> Result<CanMessage, CanError> {
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 = CanMessage::from(CanAnyFrame::from(frame));
74 frame.set_direct(CanDirect::Receive);
75 Ok(frame)
76 }
77 FD_FRAME_SIZE => {
78 let frame = unsafe { *(&buffer as *const _ as *const canfd_frame) };
79 let mut frame = CanMessage::from(CanAnyFrame::from(frame));
80 frame.set_direct(CanDirect::Receive);
81 Ok(frame)
82 }
83 XL_FRAME_SIZE => {
84 let frame = unsafe { *(&buffer as *const _ as *const canxl_frame) };
85 let mut frame = CanMessage::from(CanAnyFrame::from(frame));
86 frame.set_direct(CanDirect::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) -> Result<CanMessage, CanError> {
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: CanMessage) -> Result<(), CanError> {
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: CanMessage, timeout: Duration) -> Result<(), CanError> {
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) -> Result<(), CanError> {
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) -> Result<(), CanError> {
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) -> Result<(), CanError> {
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]) -> Result<(), CanError> {
247 match self.sockets.get(channel) {
248 Some(s) => {
249 let filters: Vec<can_filter> = filters
250 .iter()
251 .map(|&f| can_filter {
252 can_id: f.can_id,
253 can_mask: f.can_mask,
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::default()])
284 }
285
286 pub fn set_error_filter(&self, channel: &str, mask: u32) -> Result<(), CanError> {
293 match self.sockets.get(channel) {
294 Some(s) => set_socket_option(s.as_raw_fd(), SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &mask)
295 .map_err(|e| CanError::OperationError(e.to_string())),
296 None => Err(CanError::channel_not_opened(channel)),
297 }
298 }
299
300 #[inline(always)]
302 pub fn set_error_filter_drop_all(&self, channel: &str) -> Result<(), CanError> {
303 self.set_error_filter(channel, 0)
304 }
305
306 #[inline(always)]
308 pub fn set_error_filter_accept_all(&self, channel: &str) -> Result<(), CanError> {
309 self.set_error_filter(channel, ERR_MASK)
310 }
311
312 pub fn set_loopback(&self, channel: &str, enabled: bool) -> Result<(), CanError> {
318 match self.sockets.get(channel) {
319 Some(s) => {
320 let loopback = c_int::from(enabled);
321 set_socket_option(s.as_raw_fd(), SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback)
322 .map_err(|e| CanError::OperationError(e.to_string()))
323 }
324 None => Err(CanError::channel_not_opened(channel)),
325 }
326 }
327
328 pub fn set_recv_own_msgs(&self, channel: &str, enabled: bool) -> Result<(), CanError> {
333 match self.sockets.get(channel) {
334 Some(s) => {
335 let recv_own_msgs = c_int::from(enabled);
336 set_socket_option(
337 s.as_raw_fd(),
338 SOL_CAN_RAW,
339 CAN_RAW_RECV_OWN_MSGS,
340 &recv_own_msgs,
341 )
342 .map_err(|e| CanError::OperationError(e.to_string()))
343 }
344 None => Err(CanError::channel_not_opened(channel)),
345 }
346 }
347
348 pub fn set_join_filters(&self, channel: &str, enabled: bool) -> Result<(), CanError> {
354 match self.sockets.get(channel) {
355 Some(s) => {
356 let join_filters = c_int::from(enabled);
357 set_socket_option(
358 s.as_raw_fd(),
359 SOL_CAN_RAW,
360 CAN_RAW_JOIN_FILTERS,
361 &join_filters,
362 )
363 .map_err(|e| CanError::OperationError(e.to_string()))
364 }
365 None => Err(CanError::channel_not_opened(channel)),
366 }
367 }
368}