canlink_hal/capability.rs
1//! Hardware capability types.
2//!
3//! This module defines types for describing hardware capabilities and limitations.
4
5use serde::{Deserialize, Serialize};
6
7/// Hardware capability description.
8///
9/// Describes the capabilities and limitations of a CAN hardware backend.
10/// Applications can query these capabilities at runtime to adapt their behavior.
11///
12/// # Examples
13///
14/// ```
15/// use canlink_hal::{HardwareCapability, TimestampPrecision};
16///
17/// let capability = HardwareCapability {
18/// channel_count: 2,
19/// supports_canfd: true,
20/// max_bitrate: 8_000_000,
21/// supported_bitrates: vec![125_000, 250_000, 500_000, 1_000_000],
22/// filter_count: 16,
23/// timestamp_precision: TimestampPrecision::Microsecond,
24/// };
25///
26/// assert_eq!(capability.channel_count, 2);
27/// assert!(capability.supports_canfd);
28/// ```
29#[derive(Debug, Clone, PartialEq, Eq)]
30pub struct HardwareCapability {
31 /// Number of supported channels
32 pub channel_count: u8,
33
34 /// Whether CAN-FD is supported
35 pub supports_canfd: bool,
36
37 /// Maximum bitrate in bits per second
38 pub max_bitrate: u32,
39
40 /// List of supported bitrates (bps)
41 pub supported_bitrates: Vec<u32>,
42
43 /// Number of hardware filters supported
44 pub filter_count: u8,
45
46 /// Timestamp precision
47 pub timestamp_precision: TimestampPrecision,
48}
49
50impl HardwareCapability {
51 /// Create a new hardware capability description.
52 ///
53 /// # Examples
54 ///
55 /// ```
56 /// use canlink_hal::{HardwareCapability, TimestampPrecision};
57 ///
58 /// let capability = HardwareCapability::new(
59 /// 2,
60 /// true,
61 /// 8_000_000,
62 /// vec![125_000, 250_000, 500_000, 1_000_000],
63 /// 16,
64 /// TimestampPrecision::Microsecond,
65 /// );
66 /// ```
67 #[must_use]
68 pub fn new(
69 channel_count: u8,
70 supports_canfd: bool,
71 max_bitrate: u32,
72 supported_bitrates: Vec<u32>,
73 filter_count: u8,
74 timestamp_precision: TimestampPrecision,
75 ) -> Self {
76 Self {
77 channel_count,
78 supports_canfd,
79 max_bitrate,
80 supported_bitrates,
81 filter_count,
82 timestamp_precision,
83 }
84 }
85
86 /// Check if a specific bitrate is supported.
87 ///
88 /// # Examples
89 ///
90 /// ```
91 /// use canlink_hal::{HardwareCapability, TimestampPrecision};
92 ///
93 /// let capability = HardwareCapability::new(
94 /// 2,
95 /// true,
96 /// 8_000_000,
97 /// vec![125_000, 250_000, 500_000, 1_000_000],
98 /// 16,
99 /// TimestampPrecision::Microsecond,
100 /// );
101 ///
102 /// assert!(capability.supports_bitrate(500_000));
103 /// assert!(!capability.supports_bitrate(2_000_000));
104 /// ```
105 #[must_use]
106 pub fn supports_bitrate(&self, bitrate: u32) -> bool {
107 self.supported_bitrates.contains(&bitrate)
108 }
109
110 /// Check if a specific channel exists.
111 ///
112 /// # Examples
113 ///
114 /// ```
115 /// use canlink_hal::{HardwareCapability, TimestampPrecision};
116 ///
117 /// let capability = HardwareCapability::new(
118 /// 2,
119 /// true,
120 /// 8_000_000,
121 /// vec![125_000, 250_000, 500_000, 1_000_000],
122 /// 16,
123 /// TimestampPrecision::Microsecond,
124 /// );
125 ///
126 /// assert!(capability.has_channel(0));
127 /// assert!(capability.has_channel(1));
128 /// assert!(!capability.has_channel(2));
129 /// ```
130 #[must_use]
131 pub fn has_channel(&self, channel: u8) -> bool {
132 channel < self.channel_count
133 }
134}
135
136/// Timestamp precision.
137///
138/// Indicates the precision of timestamps provided by the hardware.
139///
140/// # Examples
141///
142/// ```
143/// use canlink_hal::TimestampPrecision;
144///
145/// let precision = TimestampPrecision::Microsecond;
146/// assert_eq!(precision.resolution_us(), Some(1));
147/// ```
148#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
149pub enum TimestampPrecision {
150 /// Microsecond precision (1 µs)
151 Microsecond,
152
153 /// Millisecond precision (1 ms = 1000 µs)
154 Millisecond,
155
156 /// No timestamp support
157 None,
158}
159
160impl TimestampPrecision {
161 /// Get the resolution in microseconds.
162 ///
163 /// Returns `None` if timestamps are not supported.
164 ///
165 /// # Examples
166 ///
167 /// ```
168 /// use canlink_hal::TimestampPrecision;
169 ///
170 /// assert_eq!(TimestampPrecision::Microsecond.resolution_us(), Some(1));
171 /// assert_eq!(TimestampPrecision::Millisecond.resolution_us(), Some(1000));
172 /// assert_eq!(TimestampPrecision::None.resolution_us(), None);
173 /// ```
174 #[must_use]
175 pub const fn resolution_us(&self) -> Option<u64> {
176 match self {
177 Self::Microsecond => Some(1),
178 Self::Millisecond => Some(1000),
179 Self::None => None,
180 }
181 }
182
183 /// Check if timestamps are supported.
184 ///
185 /// # Examples
186 ///
187 /// ```
188 /// use canlink_hal::TimestampPrecision;
189 ///
190 /// assert!(TimestampPrecision::Microsecond.is_supported());
191 /// assert!(TimestampPrecision::Millisecond.is_supported());
192 /// assert!(!TimestampPrecision::None.is_supported());
193 /// ```
194 #[must_use]
195 pub const fn is_supported(&self) -> bool {
196 !matches!(self, Self::None)
197 }
198}
199
200#[cfg(test)]
201mod tests {
202 use super::*;
203
204 #[test]
205 fn test_hardware_capability() {
206 let capability = HardwareCapability::new(
207 2,
208 true,
209 8_000_000,
210 vec![125_000, 250_000, 500_000, 1_000_000],
211 16,
212 TimestampPrecision::Microsecond,
213 );
214
215 assert_eq!(capability.channel_count, 2);
216 assert!(capability.supports_canfd);
217 assert_eq!(capability.max_bitrate, 8_000_000);
218 assert_eq!(capability.filter_count, 16);
219 }
220
221 #[test]
222 fn test_supports_bitrate() {
223 let capability = HardwareCapability::new(
224 2,
225 true,
226 8_000_000,
227 vec![125_000, 250_000, 500_000, 1_000_000],
228 16,
229 TimestampPrecision::Microsecond,
230 );
231
232 assert!(capability.supports_bitrate(500_000));
233 assert!(!capability.supports_bitrate(2_000_000));
234 }
235
236 #[test]
237 fn test_has_channel() {
238 let capability = HardwareCapability::new(
239 2,
240 true,
241 8_000_000,
242 vec![125_000, 250_000, 500_000, 1_000_000],
243 16,
244 TimestampPrecision::Microsecond,
245 );
246
247 assert!(capability.has_channel(0));
248 assert!(capability.has_channel(1));
249 assert!(!capability.has_channel(2));
250 }
251
252 #[test]
253 fn test_timestamp_precision() {
254 assert_eq!(TimestampPrecision::Microsecond.resolution_us(), Some(1));
255 assert_eq!(TimestampPrecision::Millisecond.resolution_us(), Some(1000));
256 assert_eq!(TimestampPrecision::None.resolution_us(), None);
257
258 assert!(TimestampPrecision::Microsecond.is_supported());
259 assert!(TimestampPrecision::Millisecond.is_supported());
260 assert!(!TimestampPrecision::None.is_supported());
261 }
262}