canlink_hal/lib.rs
1//! # `CANLink` Hardware Abstraction Layer
2//!
3//! This crate provides a unified hardware abstraction layer for CAN bus interfaces.
4//! It allows applications to work with different CAN hardware backends through a
5//! common trait-based interface.
6//!
7//! ## Features
8//!
9//! - **Unified Interface**: Single trait ([`CanBackend`]) for all hardware backends
10//! - **Backend Registry**: Runtime registration and discovery of hardware backends
11//! - **Hardware Capabilities**: Query hardware features at runtime
12//! - **Zero-Cost Abstraction**: Minimal performance overhead (< 5%)
13//! - **Type Safety**: Compile-time guarantees through Rust's type system
14//! - **Async Support**: Optional async API through feature flags
15//!
16//! ## Quick Start
17//!
18//! ```rust,ignore
19//! use canlink_hal::{BackendConfig, CanBackend, CanMessage, CanId};
20//! use canlink_mock::MockBackend;
21//!
22//! // Create and initialize backend
23//! let mut backend = MockBackend::new();
24//! let config = BackendConfig::new("mock");
25//! backend.initialize(&config)?;
26//!
27//! // Open a channel
28//! backend.open_channel(0)?;
29//!
30//! // Send a message
31//! let msg = CanMessage::new_standard(0x123, &[1, 2, 3, 4])?;
32//! backend.send_message(&msg)?;
33//!
34//! // Receive a message
35//! if let Some(msg) = backend.receive_message()? {
36//! println!("Received: ID={:?}, Data={:?}", msg.id(), msg.data());
37//! }
38//!
39//! // Clean up
40//! backend.close_channel(0)?;
41//! backend.close()?;
42//! ```
43//!
44//! ## Architecture
45//!
46//! The abstraction layer consists of several key components:
47//!
48//! ### Core Traits
49//!
50//! - **[`CanBackend`]**: Core interface that all backends must implement
51//! - `initialize()` - Initialize the backend
52//! - `send_message()` - Send a CAN message
53//! - `receive_message()` - Receive a CAN message
54//! - `open_channel()` / `close_channel()` - Channel management
55//! - `get_capability()` - Query hardware capabilities
56//!
57//! - **[`BackendFactory`]**: Factory trait for creating backend instances
58//!
59//! ### Key Types
60//!
61//! - **[`CanMessage`]**: Unified CAN message representation
62//! - Supports standard (11-bit) and extended (29-bit) IDs
63//! - Supports CAN 2.0 and CAN-FD frames
64//! - Supports remote frames
65//!
66//! - **[`CanId`]**: CAN identifier (standard or extended)
67//!
68//! - **[`HardwareCapability`]**: Hardware feature description
69//! - Channel count
70//! - CAN-FD support
71//! - Supported bitrates
72//! - Hardware filter count
73//! - Timestamp precision
74//!
75//! - **[`BackendRegistry`]**: Manages backend registration and instantiation
76//!
77//! - **[`CanError`]**: Common error types across all backends
78//!
79//! ## Usage Examples
80//!
81//! ### Basic Message Sending
82//!
83//! ```rust,ignore
84//! use canlink_hal::{CanBackend, CanMessage};
85//! use canlink_mock::MockBackend;
86//!
87//! let mut backend = MockBackend::new();
88//! backend.initialize(&config)?;
89//! backend.open_channel(0)?;
90//!
91//! // Standard CAN message
92//! let msg = CanMessage::new_standard(0x123, &[0xAA, 0xBB, 0xCC, 0xDD])?;
93//! backend.send_message(&msg)?;
94//!
95//! // Extended ID message
96//! let msg = CanMessage::new_extended(0x12345678, &[1, 2, 3, 4, 5, 6, 7, 8])?;
97//! backend.send_message(&msg)?;
98//!
99//! // CAN-FD message (if supported)
100//! let data = vec![0; 64]; // Up to 64 bytes
101//! let msg = CanMessage::new_fd(CanId::Standard(0x200), &data)?;
102//! backend.send_message(&msg)?;
103//! ```
104//!
105//! ### Capability-Based Adaptation
106//!
107//! ```rust,ignore
108//! use canlink_hal::{CanBackend, CanMessage, CanId};
109//!
110//! let capability = backend.get_capability()?;
111//!
112//! // Adapt message type based on hardware support
113//! let data = vec![0; 12];
114//! let msg = if capability.supports_canfd {
115//! CanMessage::new_fd(CanId::Standard(0x123), &data)?
116//! } else {
117//! // Split into multiple CAN 2.0 messages
118//! CanMessage::new_standard(0x123, &data[..8])?
119//! };
120//!
121//! // Check bitrate support
122//! if capability.supports_bitrate(1_000_000) {
123//! println!("1 Mbps is supported");
124//! }
125//!
126//! // Check channel availability
127//! if capability.has_channel(2) {
128//! backend.open_channel(2)?;
129//! }
130//! ```
131//!
132//! ### Error Handling
133//!
134//! ```rust,ignore
135//! use canlink_hal::{CanError, CanBackend};
136//!
137//! match backend.send_message(&msg) {
138//! Ok(_) => println!("Message sent successfully"),
139//! Err(CanError::SendFailed { reason }) => {
140//! eprintln!("Send failed: {}", reason);
141//! }
142//! Err(CanError::BusError { kind }) => {
143//! eprintln!("Bus error: {:?}", kind);
144//! }
145//! Err(e) => eprintln!("Other error: {}", e),
146//! }
147//! ```
148//!
149//! ### Backend Registry
150//!
151//! ```rust,ignore
152//! use canlink_hal::{BackendRegistry, BackendConfig};
153//! use canlink_mock::MockBackendFactory;
154//! use std::sync::Arc;
155//!
156//! // Get global registry
157//! let registry = BackendRegistry::global();
158//!
159//! // Register a backend
160//! let factory = Arc::new(MockBackendFactory::new());
161//! registry.register(factory)?;
162//!
163//! // List available backends
164//! for name in registry.list_backends() {
165//! println!("Available backend: {}", name);
166//! }
167//!
168//! // Create backend instance
169//! let config = BackendConfig::new("mock");
170//! let mut backend = registry.create("mock", &config)?;
171//! ```
172//!
173//! ## Testing
174//!
175//! The crate includes a mock backend for testing without hardware:
176//!
177//! ```rust,ignore
178//! use canlink_hal::{CanBackend, CanMessage, CanId};
179//! use canlink_mock::MockBackend;
180//!
181//! #[test]
182//! fn test_can_communication() {
183//! let mut backend = MockBackend::new();
184//! backend.initialize(&config).unwrap();
185//! backend.open_channel(0).unwrap();
186//!
187//! // Send message
188//! let msg = CanMessage::new_standard(0x123, &[1, 2, 3]).unwrap();
189//! backend.send_message(&msg).unwrap();
190//!
191//! // Verify message was sent
192//! assert!(backend.verify_message_sent(CanId::Standard(0x123)));
193//! }
194//! ```
195//!
196//! ## Feature Flags
197//!
198//! - `async` - Enable async API support
199//! - `async-tokio` - Use tokio runtime for async operations
200//! - `async-async-std` - Use async-std runtime for async operations
201//! - `tracing` - Enable logging support via tracing framework
202//! - `hot-reload` - Enable configuration hot-reload support
203//! - `full` - Enable all features
204//!
205//! ## Performance
206//!
207//! The abstraction layer is designed for minimal overhead:
208//!
209//! - Trait method calls are typically inlined
210//! - Zero-copy message passing where possible
211//! - Abstraction overhead < 5% compared to direct hardware access
212//!
213//! ## Thread Safety
214//!
215//! Backend implementations follow an external synchronization model:
216//!
217//! - Backends are `Send` but not `Sync`
218//! - Each thread should have its own backend instance
219//! - Use channels or locks for cross-thread communication
220//!
221//! ## Supported Backends
222//!
223//! - **Mock**: Software simulation for testing (included)
224//! - **`SocketCAN`**: Linux CAN interface (planned)
225//! - **PCAN**: PEAK-System CAN adapters (planned)
226//! - **IXXAT**: HMS IXXAT CAN interfaces (planned)
227//! - **Kvaser**: Kvaser CAN devices (planned)
228//!
229//! ## See Also
230//!
231//! - [`canlink-mock`](https://docs.rs/canlink-mock) - Mock backend for testing
232//! - [`canlink-cli`](https://docs.rs/canlink-cli) - Command-line interface
233//! - Examples: see the workspace `examples/` directory
234//!
235
236#![deny(missing_docs)]
237#![warn(clippy::all)]
238#![warn(clippy::pedantic)]
239#![allow(clippy::module_name_repetitions)]
240
241// Core modules
242pub mod backend;
243pub mod capability;
244pub mod config;
245pub mod error;
246pub mod message;
247pub mod registry;
248pub mod state;
249pub mod version;
250
251// New modules introduced in v0.2.0 (003-async-and-filtering)
252pub mod filter;
253pub mod monitor;
254pub mod queue;
255
256// Conditional modules
257#[cfg(feature = "tracing")]
258pub mod logging;
259
260#[cfg(feature = "hot-reload")]
261pub mod hot_reload;
262
263// Periodic message sending (004 spec FR-001 to FR-006)
264#[cfg(feature = "periodic")]
265pub mod periodic;
266
267// ISO-TP protocol support (004 spec FR-007 to FR-019)
268#[cfg(feature = "isotp")]
269pub mod isotp;
270
271// Resource management documentation
272pub mod resource;
273
274// Re-exports
275#[cfg(feature = "async")]
276pub use backend::CanBackendAsync;
277pub use backend::{
278 retry_initialize, switch_backend, BackendFactory, CanBackend, MessageRateMonitor,
279};
280pub use capability::{HardwareCapability, TimestampPrecision};
281pub use config::{BackendConfig, CanlinkConfig};
282pub use error::{BusErrorKind, CanError, CanResult};
283pub use error::{FilterError, FilterResult};
284pub use error::{MonitorError, MonitorResult};
285pub use error::{QueueError, QueueResult};
286pub use message::{CanId, CanMessage, MessageFlags, Timestamp};
287pub use registry::{BackendInfo, BackendRegistry};
288pub use state::BackendState;
289pub use version::BackendVersion;
290
291// Periodic message sending re-exports (004 spec)
292#[cfg(feature = "periodic")]
293pub use periodic::{
294 run_scheduler, PeriodicMessage, PeriodicScheduler, PeriodicStats, SchedulerCommand,
295};
296
297// ISO-TP protocol re-exports (004 spec)
298#[cfg(feature = "isotp")]
299pub use isotp::{
300 AddressingMode, FlowStatus, FrameSize, IsoTpConfig, IsoTpConfigBuilder, IsoTpError, IsoTpFrame,
301 IsoTpState, RxState, StMin, TxState,
302};