Skip to main content

can_hal_socketcan/
driver.rs

1use can_hal::driver::{ChannelBuilder, Driver, DriverFd};
2
3use crate::channel::SocketCanChannel;
4use crate::error::SocketCanError;
5
6/// How the CAN interface is identified.
7enum InterfaceSpec {
8    Index(u32),
9    Name(String),
10}
11
12/// SocketCAN driver — factory for opening CAN channels.
13///
14/// Implements the [`Driver`] trait using kernel interface indices.
15/// Also provides [`channel_by_name`](SocketCanDriver::channel_by_name) for
16/// opening by interface name (e.g., `"can0"`, `"vcan0"`).
17///
18/// # Example
19///
20/// ```rust,no_run
21/// use can_hal::{Driver, ChannelBuilder};
22/// use can_hal_socketcan::SocketCanDriver;
23///
24/// let driver = SocketCanDriver::new();
25/// let mut channel = driver
26///     .channel_by_name("vcan0")
27///     .unwrap()
28///     .bitrate(500_000)
29///     .unwrap()
30///     .connect()
31///     .unwrap();
32/// ```
33pub struct SocketCanDriver;
34
35impl SocketCanDriver {
36    #[must_use]
37    pub const fn new() -> Self {
38        Self
39    }
40
41    /// Begin configuring a channel on the named interface.
42    pub fn channel_by_name(&self, name: &str) -> Result<SocketCanChannelBuilder, SocketCanError> {
43        Ok(SocketCanChannelBuilder {
44            interface: InterfaceSpec::Name(name.to_string()),
45            bitrate: None,
46            data_bitrate: None,
47            sample_point: None,
48        })
49    }
50}
51
52impl Default for SocketCanDriver {
53    fn default() -> Self {
54        Self::new()
55    }
56}
57
58impl DriverFd for SocketCanDriver {}
59
60impl Driver for SocketCanDriver {
61    type Channel = SocketCanChannel;
62    type Builder = SocketCanChannelBuilder;
63    type Error = SocketCanError;
64
65    fn channel(&self, index: u32) -> Result<Self::Builder, Self::Error> {
66        Ok(SocketCanChannelBuilder {
67            interface: InterfaceSpec::Index(index),
68            bitrate: None,
69            data_bitrate: None,
70            sample_point: None,
71        })
72    }
73}
74
75/// Builder for configuring a SocketCAN channel before connecting.
76///
77/// The `bitrate`, `data_bitrate`, and `sample_point` methods store values but
78/// do **not** apply them — SocketCAN bitrate configuration is done at the OS
79/// level via `ip link set` or netlink, not through the socket API. Configure
80/// your interface before calling [`connect`](ChannelBuilder::connect).
81pub struct SocketCanChannelBuilder {
82    interface: InterfaceSpec,
83    bitrate: Option<u32>,
84    data_bitrate: Option<u32>,
85    sample_point: Option<f32>,
86}
87
88impl ChannelBuilder for SocketCanChannelBuilder {
89    type Channel = SocketCanChannel;
90    type Error = SocketCanError;
91
92    fn bitrate(mut self, bitrate: u32) -> Result<Self, Self::Error> {
93        self.bitrate = Some(bitrate);
94        Ok(self)
95    }
96
97    fn data_bitrate(mut self, bitrate: u32) -> Result<Self, Self::Error> {
98        self.data_bitrate = Some(bitrate);
99        Ok(self)
100    }
101
102    fn sample_point(mut self, sample_point: f32) -> Result<Self, Self::Error> {
103        self.sample_point = Some(sample_point);
104        Ok(self)
105    }
106
107    fn connect(self) -> Result<Self::Channel, Self::Error> {
108        match self.interface {
109            InterfaceSpec::Index(idx) => SocketCanChannel::open_iface(idx),
110            InterfaceSpec::Name(ref name) => SocketCanChannel::open(name),
111        }
112    }
113}