Skip to main content

host_can/adapter/socketcan/
mod.rs

1//! SocketCAN adapter
2use 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 loopback = ifname.starts_with("vcan");
35        let rx = CanSocket::open(ifname)?;
36        rx.set_loopback(loopback)?;
37        let tx = CanSocket::open(ifname)?;
38        tx.set_loopback(loopback)?;
39        Ok(Self {
40            rx: RefCell::new(rx),
41            tx: RefCell::new(tx),
42        })
43    }
44}
45
46impl Adapter for SocketCanAdapter {
47    fn send(&self, frame: &CanFrame) -> Result<(), Box<AdapterError>> {
48        let frame = SocketCanFrame::new(frame.id(), frame.data())
49            .ok_or(AdapterError::WriteFailed)?;
50
51        self.tx
52            .borrow_mut()
53            .transmit(&frame)
54            .or(Err(AdapterError::WriteFailed))?;
55
56        Ok(())
57    }
58
59    fn recv(
60        &self,
61        timeout: Option<Duration>,
62    ) -> Result<CanFrame, Box<AdapterError>> {
63        if let Some(timeout) = timeout {
64            let fd = unsafe {
65                let socket = self.rx.borrow();
66                BorrowedFd::borrow_raw(socket.as_raw_fd())
67            };
68            let pollfd = PollFd::new(fd, PollFlags::POLLIN);
69
70            let poll_timeout = timeout.try_into().unwrap_or(PollTimeout::MAX);
71
72            match poll(&mut [pollfd], poll_timeout) {
73                Ok(1) => {}
74                Ok(0) => {
75                    return Err(Box::new(AdapterError::ReadTimeout));
76                }
77                _ => return Err(Box::new(AdapterError::ReadFailed)),
78            }
79        }
80
81        match self.rx.borrow_mut().receive() {
82            Ok(frame) => {
83                let frame = CanFrame::new(frame.id(), frame.data())
84                    .ok_or(Box::new(AdapterError::ReadFailed))?;
85                Ok(frame)
86            }
87            _ => Err(Box::new(AdapterError::ReadFailed)),
88        }
89    }
90}