1use std::fmt;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub enum CanBitrate {
5 B10K = 10_000,
6 B20K = 20_000,
7 B50K = 50_000,
8 B100K = 100_000,
9 B125K = 125_000,
10 B250K = 250_000,
11 B500K = 500_000,
12 B1M = 1_000_000,
13}
14
15impl fmt::Display for CanBitrate {
16 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17 let label = match self {
18 CanBitrate::B1M => "1 Mbit".to_string(),
19 CanBitrate::B500K => "500 kbit".to_string(),
20 CanBitrate::B250K => "250 kbit".to_string(),
21 CanBitrate::B125K => "125 kbit".to_string(),
22 CanBitrate::B100K => "100 kbit".to_string(),
23 CanBitrate::B50K => "50 kbit".to_string(),
24 CanBitrate::B20K => "20 kbit".to_string(),
25 CanBitrate::B10K => "10 kbit".to_string(),
26 };
27
28 write!(f, "{} ({})", label, *self as u32)
29 }
30}
31
32impl CanBitrate {
33 pub fn bitrate(&self) -> u32 {
34 *self as u32
35 }
36 pub fn can_bitrates() -> Vec<CanBitrate> {
37 let mut bitrates = vec![
38 CanBitrate::B10K,
39 CanBitrate::B20K,
40 CanBitrate::B50K,
41 CanBitrate::B100K,
42 CanBitrate::B125K,
43 CanBitrate::B250K,
44 CanBitrate::B500K,
45 CanBitrate::B1M,
46 ];
47
48 bitrates.sort_by_key(|b| std::cmp::Reverse(*b as u32));
49 bitrates
50 }
51}
52
53#[derive(Debug, Clone)]
54pub struct SlcanSpeed {
55 pub bitrate: u32,
56 pub flag: &'static str,
57}
58
59impl fmt::Display for SlcanSpeed {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 let label = match self.bitrate {
62 1_000_000 => "1 Mbit".to_string(),
63 _ if self.bitrate >= 1_000 => format!("{} kbit", self.bitrate / 1_000),
64 _ => self.bitrate.to_string(),
65 };
66
67 write!(f, "{:<10} ({}, {})", label, self.bitrate, self.flag)
68 }
69}
70
71pub fn slcan_speeds() -> Vec<SlcanSpeed> {
72 let mut speeds = vec![
73 SlcanSpeed {
74 bitrate: 10_000,
75 flag: "s0",
76 },
77 SlcanSpeed {
78 bitrate: 20_000,
79 flag: "s1",
80 },
81 SlcanSpeed {
82 bitrate: 50_000,
83 flag: "s2",
84 },
85 SlcanSpeed {
86 bitrate: 100_000,
87 flag: "s3",
88 },
89 SlcanSpeed {
90 bitrate: 125_000,
91 flag: "s4",
92 },
93 SlcanSpeed {
94 bitrate: 250_000,
95 flag: "s5",
96 },
97 SlcanSpeed {
98 bitrate: 500_000,
99 flag: "s6",
100 },
101 SlcanSpeed {
102 bitrate: 800_000,
103 flag: "s7",
104 },
105 SlcanSpeed {
106 bitrate: 1_000_000,
107 flag: "s8",
108 },
109 ];
110
111 speeds.sort_by_key(|b| std::cmp::Reverse(b.bitrate));
112 speeds
113}
114
115#[derive(Debug, Clone)]
116pub enum CanMode {
117 Native,
118 Slcan,
119 Virtual,
120}
121
122impl fmt::Display for CanMode {
123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124 match self {
125 CanMode::Native => write!(f, "Native CAN bus"),
126 CanMode::Slcan => write!(f, "Non-native CAN bus (slcand)"),
127 CanMode::Virtual => write!(f, "Virtual CAN bus (vcan)"),
128 }
129 }
130}
131
132#[derive(Debug, Clone)]
133pub struct NativeConfig {
134 pub iface: String,
135 pub bitrate: CanBitrate,
136}
137
138impl NativeConfig {
139 pub fn new(iface: String, bitrate: CanBitrate) -> Self {
140 Self { iface, bitrate }
141 }
142}
143
144#[derive(Debug, Clone)]
145pub struct SlcanConfig {
146 pub tty: String,
147 pub iface: String,
148 pub speed: SlcanSpeed,
149 pub uart_baud: u32,
150}
151
152impl SlcanConfig {
153 pub fn new(tty: String, iface: String, speed: SlcanSpeed, uart_baud: u32) -> Self {
154 Self {
155 tty,
156 iface,
157 speed,
158 uart_baud,
159 }
160 }
161}
162
163#[derive(Debug, Clone)]
164pub struct VirtualConfig {
165 pub iface: String,
166}
167
168impl VirtualConfig {
169 pub fn new(iface: String) -> Self {
170 Self { iface }
171 }
172}
173
174#[derive(Debug, Clone)]
175pub enum CanConfig {
176 Native(NativeConfig),
177 Slcan(SlcanConfig),
178 Virtual(VirtualConfig),
179}
180
181impl CanConfig {
182 pub fn new(
183 mode: CanMode,
184 iface: String,
185 bitrate: Option<CanBitrate>,
186 slcan_speed: Option<SlcanSpeed>,
187 uart_baud: Option<u32>,
188 ) -> Self {
189 match mode {
190 CanMode::Native => CanConfig::Native(NativeConfig {
191 iface,
192 bitrate: bitrate.expect("Bitrate is required for Native mode"),
193 }),
194 CanMode::Slcan => CanConfig::Slcan(SlcanConfig {
195 tty: "/dev/ttyUSB0".to_string(), iface,
197 speed: slcan_speed.expect("SLCAN speed is required for Slcan mode"),
198 uart_baud: uart_baud.expect("UART baud rate is required for Slcan mode"),
199 }),
200 CanMode::Virtual => CanConfig::Virtual(VirtualConfig { iface }),
201 }
202 }
203 pub fn iface(&self) -> &str {
204 match self {
205 CanConfig::Native(cfg) => &cfg.iface,
206 CanConfig::Slcan(cfg) => &cfg.iface,
207 CanConfig::Virtual(cfg) => &cfg.iface,
208 }
209 }
210
211 pub fn set_iface(&mut self, new_iface: String) {
212 match self {
213 CanConfig::Native(cfg) => cfg.iface = new_iface,
214 CanConfig::Slcan(cfg) => cfg.iface = new_iface,
215 CanConfig::Virtual(cfg) => cfg.iface = new_iface,
216 }
217 }
218}
219
220#[derive(Debug, Clone, Copy, PartialEq, Eq)]
221pub enum ExistingIfaceAction {
222 Replace,
223 Rename,
224 Skip,
225 Cancel,
226}
227
228#[derive(Debug, Clone, Copy, PartialEq, Eq)]
229pub enum InterfaceResolution {
230 Proceed,
231 SkipSetup,
232}