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    pub fn new() -> Self {
37        SocketCanDriver
38    }
39
40    /// Begin configuring a channel on the named interface.
41    pub fn channel_by_name(&self, name: &str) -> Result<SocketCanChannelBuilder, SocketCanError> {
42        Ok(SocketCanChannelBuilder {
43            interface: InterfaceSpec::Name(name.to_string()),
44            bitrate: None,
45            data_bitrate: None,
46            sample_point: None,
47        })
48    }
49}
50
51impl Default for SocketCanDriver {
52    fn default() -> Self {
53        Self::new()
54    }
55}
56
57impl DriverFd for SocketCanDriver {}
58
59impl Driver for SocketCanDriver {
60    type Channel = SocketCanChannel;
61    type Builder = SocketCanChannelBuilder;
62    type Error = SocketCanError;
63
64    fn channel(&self, index: u32) -> Result<Self::Builder, Self::Error> {
65        Ok(SocketCanChannelBuilder {
66            interface: InterfaceSpec::Index(index),
67            bitrate: None,
68            data_bitrate: None,
69            sample_point: None,
70        })
71    }
72}
73
74/// Builder for configuring a SocketCAN channel before connecting.
75///
76/// The `bitrate`, `data_bitrate`, and `sample_point` methods store values but
77/// do **not** apply them — SocketCAN bitrate configuration is done at the OS
78/// level via `ip link set` or netlink, not through the socket API. Configure
79/// your interface before calling [`connect`](ChannelBuilder::connect).
80pub struct SocketCanChannelBuilder {
81    interface: InterfaceSpec,
82    bitrate: Option<u32>,
83    data_bitrate: Option<u32>,
84    sample_point: Option<f32>,
85}
86
87impl ChannelBuilder for SocketCanChannelBuilder {
88    type Channel = SocketCanChannel;
89    type Error = SocketCanError;
90
91    fn bitrate(mut self, bitrate: u32) -> Result<Self, Self::Error> {
92        self.bitrate = Some(bitrate);
93        Ok(self)
94    }
95
96    fn data_bitrate(mut self, bitrate: u32) -> Result<Self, Self::Error> {
97        self.data_bitrate = Some(bitrate);
98        Ok(self)
99    }
100
101    fn sample_point(mut self, sample_point: f32) -> Result<Self, Self::Error> {
102        self.sample_point = Some(sample_point);
103        Ok(self)
104    }
105
106    fn connect(self) -> Result<Self::Channel, Self::Error> {
107        match self.interface {
108            InterfaceSpec::Index(idx) => SocketCanChannel::open_iface(idx),
109            InterfaceSpec::Name(ref name) => SocketCanChannel::open(name),
110        }
111    }
112}