host_can/adapter/socketcan/
mod.rs1use crate::adapter::{Adapter, AdapterBaud, AdapterError};
3use crate::frame::{CanFrame, Frame};
4
5use core::cell::RefCell;
6use std::os::fd::AsRawFd;
7use std::os::unix::io::BorrowedFd;
8use std::result::Result;
9use std::time::Duration;
10
11use nix::poll::{PollFd, PollFlags, PollTimeout, poll};
12use socketcan::{
13 BlockingCan, CanFrame as SocketCanFrame, CanInterface, CanSocket, Socket,
14};
15
16pub struct SocketCanAdapter {
17 rx: RefCell<CanSocket>,
18 tx: RefCell<CanSocket>,
19}
20
21impl SocketCanAdapter {
22 pub fn new(
23 ifname: &str,
24 baud: AdapterBaud,
25 ) -> Result<Self, Box<dyn std::error::Error>> {
26 let iface = CanInterface::open(ifname)?;
27 if let Some(bit_rate) = iface.bit_rate()?
28 && bit_rate as AdapterBaud != baud
29 {
30 return Err(Box::new(AdapterError::UnsupportedBaud));
31 }
32
33 Ok(Self {
34 rx: RefCell::new(CanSocket::open(ifname)?),
35 tx: RefCell::new(CanSocket::open(ifname)?),
36 })
37 }
38}
39
40impl Adapter for SocketCanAdapter {
41 fn send(&self, frame: &CanFrame) -> Result<(), Box<AdapterError>> {
42 let frame = SocketCanFrame::new(frame.id(), frame.data())
43 .ok_or(AdapterError::WriteFailed)?;
44
45 self.tx
46 .borrow_mut()
47 .transmit(&frame)
48 .or(Err(AdapterError::WriteFailed))?;
49
50 Ok(())
51 }
52
53 fn recv(
54 &self,
55 timeout: Option<Duration>,
56 ) -> Result<CanFrame, Box<AdapterError>> {
57 if let Some(timeout) = timeout {
58 let fd = unsafe {
59 let socket = self.rx.borrow();
60 BorrowedFd::borrow_raw(socket.as_raw_fd())
61 };
62 let pollfd = PollFd::new(fd, PollFlags::POLLIN);
63
64 let poll_timeout = timeout.try_into().unwrap_or(PollTimeout::MAX);
65
66 match poll(&mut [pollfd], poll_timeout) {
67 Ok(1) => {}
68 Ok(0) => {
69 return Err(Box::new(AdapterError::ReadTimeout));
70 }
71 _ => return Err(Box::new(AdapterError::ReadFailed)),
72 }
73 }
74
75 match self.rx.borrow_mut().receive() {
76 Ok(frame) => {
77 let frame = CanFrame::new(frame.id(), frame.data())
78 .ok_or(Box::new(AdapterError::ReadFailed))?;
79 Ok(frame)
80 }
81 _ => Err(Box::new(AdapterError::ReadFailed)),
82 }
83 }
84}