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 SocketOptions,
15};
16
17pub struct SocketCanAdapter {
18 rx: RefCell<CanSocket>,
19 tx: RefCell<CanSocket>,
20}
21
22impl SocketCanAdapter {
23 pub fn new(
24 ifname: &str,
25 baud: AdapterBaud,
26 ) -> Result<Self, Box<dyn std::error::Error>> {
27 let iface = CanInterface::open(ifname)?;
28 if let Some(bit_rate) = iface.bit_rate()?
29 && bit_rate as AdapterBaud != baud
30 {
31 return Err(Box::new(AdapterError::UnsupportedBaud));
32 }
33
34 let rx = CanSocket::open(ifname)?;
35 rx.set_loopback(false)?;
36 let tx = CanSocket::open(ifname)?;
37 tx.set_loopback(false)?;
38 Ok(Self {
39 rx: RefCell::new(rx),
40 tx: RefCell::new(tx),
41 })
42 }
43}
44
45impl Adapter for SocketCanAdapter {
46 fn send(&self, frame: &CanFrame) -> Result<(), Box<AdapterError>> {
47 let frame = SocketCanFrame::new(frame.id(), frame.data())
48 .ok_or(AdapterError::WriteFailed)?;
49
50 self.tx
51 .borrow_mut()
52 .transmit(&frame)
53 .or(Err(AdapterError::WriteFailed))?;
54
55 Ok(())
56 }
57
58 fn recv(
59 &self,
60 timeout: Option<Duration>,
61 ) -> Result<CanFrame, Box<AdapterError>> {
62 if let Some(timeout) = timeout {
63 let fd = unsafe {
64 let socket = self.rx.borrow();
65 BorrowedFd::borrow_raw(socket.as_raw_fd())
66 };
67 let pollfd = PollFd::new(fd, PollFlags::POLLIN);
68
69 let poll_timeout = timeout.try_into().unwrap_or(PollTimeout::MAX);
70
71 match poll(&mut [pollfd], poll_timeout) {
72 Ok(1) => {}
73 Ok(0) => {
74 return Err(Box::new(AdapterError::ReadTimeout));
75 }
76 _ => return Err(Box::new(AdapterError::ReadFailed)),
77 }
78 }
79
80 match self.rx.borrow_mut().receive() {
81 Ok(frame) => {
82 let frame = CanFrame::new(frame.id(), frame.data())
83 .ok_or(Box::new(AdapterError::ReadFailed))?;
84 Ok(frame)
85 }
86 _ => Err(Box::new(AdapterError::ReadFailed)),
87 }
88 }
89}