Skip to main content

can_hal_socketcan/
driver.rs

1use crate::channel::SocketCanChannel;
2use crate::error::SocketCanError;
3
4/// How the CAN interface is identified.
5enum InterfaceSpec {
6    Index(u32),
7    Name(String),
8}
9
10/// SocketCAN driver - factory for opening CAN channels.
11///
12/// SocketCAN bitrate, sample point, and FD timing are configured at the OS
13/// level via `ip link set` or netlink - not through the socket API - so this
14/// builder intentionally has no timing methods. Configure the interface
15/// before calling [`connect`](SocketCanChannelBuilder::connect):
16///
17/// ```bash
18/// sudo ip link set can0 type can bitrate 500000
19/// sudo ip link set can0 up
20/// ```
21///
22/// # Example
23///
24/// ```rust,no_run
25/// use can_hal_socketcan::SocketCanDriver;
26///
27/// let driver = SocketCanDriver::new();
28/// let mut channel = driver
29///     .channel_by_name("vcan0")
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    #[must_use]
43    pub fn channel_by_name(&self, name: &str) -> SocketCanChannelBuilder {
44        SocketCanChannelBuilder {
45            interface: InterfaceSpec::Name(name.to_string()),
46        }
47    }
48
49    /// Begin configuring a channel at the given 0-based interface index.
50    #[must_use]
51    pub const fn channel(&self, index: u32) -> SocketCanChannelBuilder {
52        SocketCanChannelBuilder {
53            interface: InterfaceSpec::Index(index),
54        }
55    }
56}
57
58impl Default for SocketCanDriver {
59    fn default() -> Self {
60        Self::new()
61    }
62}
63
64/// Builder for opening a SocketCAN channel.
65///
66/// SocketCAN bitrate is OS-managed, so this builder only chooses the
67/// interface - there are deliberately no methods to set bitrate, sample
68/// point, or FD timing.
69pub struct SocketCanChannelBuilder {
70    interface: InterfaceSpec,
71}
72
73impl SocketCanChannelBuilder {
74    /// Open the channel and go on-bus.
75    pub fn connect(self) -> Result<SocketCanChannel, SocketCanError> {
76        match self.interface {
77            InterfaceSpec::Index(idx) => SocketCanChannel::open_iface(idx),
78            InterfaceSpec::Name(ref name) => SocketCanChannel::open(name),
79        }
80    }
81}