host-can 0.1.5

Host library for CAN adapters
Documentation
//! SocketCAN adapter
use crate::adapter::{Adapter, AdapterBaud, AdapterError};
use crate::frame::{CanFrame, Frame};

use core::cell::RefCell;
use std::os::fd::AsRawFd;
use std::os::unix::io::BorrowedFd;
use std::result::Result;
use std::time::Duration;

use nix::poll::{PollFd, PollFlags, PollTimeout, poll};
use socketcan::{
    BlockingCan, CanFrame as SocketCanFrame, CanInterface, CanSocket, Socket,
    SocketOptions,
};

pub struct SocketCanAdapter {
    rx: RefCell<CanSocket>,
    tx: RefCell<CanSocket>,
}

impl SocketCanAdapter {
    pub fn new(
        ifname: &str,
        baud: AdapterBaud,
    ) -> Result<Self, Box<dyn std::error::Error>> {
        let iface = CanInterface::open(ifname)?;
        if let Some(bit_rate) = iface.bit_rate()?
            && bit_rate as AdapterBaud != baud
        {
            return Err(Box::new(AdapterError::UnsupportedBaud));
        }

        let loopback = ifname.starts_with("vcan");
        let rx = CanSocket::open(ifname)?;
        rx.set_loopback(loopback)?;
        let tx = CanSocket::open(ifname)?;
        tx.set_loopback(loopback)?;
        Ok(Self {
            rx: RefCell::new(rx),
            tx: RefCell::new(tx),
        })
    }
}

impl Adapter for SocketCanAdapter {
    fn send(&self, frame: &CanFrame) -> Result<(), Box<AdapterError>> {
        let frame = SocketCanFrame::new(frame.id(), frame.data())
            .ok_or(AdapterError::WriteFailed)?;

        self.tx
            .borrow_mut()
            .transmit(&frame)
            .or(Err(AdapterError::WriteFailed))?;

        Ok(())
    }

    fn recv(
        &self,
        timeout: Option<Duration>,
    ) -> Result<CanFrame, Box<AdapterError>> {
        if let Some(timeout) = timeout {
            let fd = unsafe {
                let socket = self.rx.borrow();
                BorrowedFd::borrow_raw(socket.as_raw_fd())
            };
            let pollfd = PollFd::new(fd, PollFlags::POLLIN);

            let poll_timeout = timeout.try_into().unwrap_or(PollTimeout::MAX);

            match poll(&mut [pollfd], poll_timeout) {
                Ok(1) => {}
                Ok(0) => {
                    return Err(Box::new(AdapterError::ReadTimeout));
                }
                _ => return Err(Box::new(AdapterError::ReadFailed)),
            }
        }

        match self.rx.borrow_mut().receive() {
            Ok(frame) => {
                let frame = CanFrame::new(frame.id(), frame.data())
                    .ok_or(Box::new(AdapterError::ReadFailed))?;
                Ok(frame)
            }
            _ => Err(Box::new(AdapterError::ReadFailed)),
        }
    }
}