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}