Skip to main content

linux_socketcan_iso_tp/
non_linux.rs

1//! Non-Linux stubs.
2//!
3//! This crate targets Linux kernel `CAN_ISOTP` sockets. On non-Linux targets we provide
4//! compile-time stubs so downstream crates can build with `cfg` gating.
5
6#[cfg(feature = "tokio")]
7use can_isotp_interface::{IsoTpAsyncEndpoint, IsoTpAsyncEndpointRecvInto, RecvMetaIntoStatus};
8use can_isotp_interface::{
9    IsoTpEndpoint, IsoTpRxFlowControlConfig, RecvControl, RecvError, RecvMeta, RecvStatus,
10    RxFlowControl, SendError,
11};
12use core::time::Duration;
13use embedded_can::Id;
14
15/// ISO-TP socket error type (non-Linux stub).
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub struct Error;
18
19impl core::fmt::Display for Error {
20    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
21        write!(
22            f,
23            "linux-socketcan-iso-tp is only supported on Linux targets"
24        )
25    }
26}
27
28impl std::error::Error for Error {}
29
30/// Socket-level ISO-TP options.
31#[derive(Debug, Clone, Default)]
32pub struct IsoTpSocketOptions {
33    pub flags: u32,
34    pub frame_txtime: Option<Duration>,
35    pub ext_address: Option<u8>,
36    pub tx_padding: Option<u8>,
37    pub rx_padding: Option<u8>,
38    pub rx_ext_address: Option<u8>,
39}
40
41/// Flow control options advertised by the kernel.
42#[derive(Debug, Clone, Copy)]
43pub struct IsoTpFlowControlOptions {
44    pub block_size: u8,
45    pub st_min: u8,
46    pub wft_max: u8,
47}
48
49impl IsoTpFlowControlOptions {
50    pub fn new(block_size: u8, st_min: u8, wft_max: u8) -> Self {
51        Self {
52            block_size,
53            st_min,
54            wft_max,
55        }
56    }
57}
58
59/// Link-layer options for kernel ISO-TP sockets.
60#[derive(Debug, Clone, Copy)]
61pub struct IsoTpLinkLayerOptions {
62    pub mtu: u8,
63    pub tx_dl: u8,
64    pub tx_flags: u8,
65}
66
67impl IsoTpLinkLayerOptions {
68    pub fn new(mtu: u8, tx_dl: u8, tx_flags: u8) -> Self {
69        Self {
70            mtu,
71            tx_dl,
72            tx_flags,
73        }
74    }
75}
76
77/// Kernel ISO-TP socket configuration.
78#[derive(Debug, Clone)]
79pub struct IsoTpKernelOptions {
80    pub max_rx_payload: usize,
81    pub socket: IsoTpSocketOptions,
82    pub flow_control: Option<IsoTpFlowControlOptions>,
83    pub link_layer: Option<IsoTpLinkLayerOptions>,
84    pub force_tx_stmin: Option<Duration>,
85    pub force_rx_stmin: Option<Duration>,
86}
87
88impl Default for IsoTpKernelOptions {
89    fn default() -> Self {
90        Self {
91            max_rx_payload: 4095,
92            socket: IsoTpSocketOptions::default(),
93            flow_control: None,
94            link_layer: None,
95            force_tx_stmin: None,
96            force_rx_stmin: None,
97        }
98    }
99}
100
101/// Kernel ISO-TP endpoint using a single socket (non-Linux stub).
102#[derive(Debug)]
103pub struct SocketCanIsoTp;
104
105impl SocketCanIsoTp {
106    pub fn open(
107        _iface: &str,
108        _rx_id: Id,
109        _tx_id: Id,
110        _options: &IsoTpKernelOptions,
111    ) -> Result<Self, Error> {
112        Err(Error)
113    }
114}
115
116impl IsoTpEndpoint for SocketCanIsoTp {
117    type Error = Error;
118
119    fn send_to(
120        &mut self,
121        _to: u8,
122        _payload: &[u8],
123        _timeout: Duration,
124    ) -> Result<(), SendError<Self::Error>> {
125        Err(SendError::Backend(Error))
126    }
127
128    fn send_functional_to(
129        &mut self,
130        _functional_to: u8,
131        _payload: &[u8],
132        _timeout: Duration,
133    ) -> Result<(), SendError<Self::Error>> {
134        Err(SendError::Backend(Error))
135    }
136
137    fn recv_one<Cb>(
138        &mut self,
139        _timeout: Duration,
140        _on_payload: Cb,
141    ) -> Result<RecvStatus, RecvError<Self::Error>>
142    where
143        Cb: FnMut(RecvMeta, &[u8]) -> Result<RecvControl, Self::Error>,
144    {
145        Err(RecvError::Backend(Error))
146    }
147}
148
149impl IsoTpRxFlowControlConfig for SocketCanIsoTp {
150    type Error = Error;
151
152    fn set_rx_flow_control(&mut self, _fc: RxFlowControl) -> Result<(), Self::Error> {
153        Err(Error)
154    }
155}
156
157/// Tokio-native async wrapper around [`SocketCanIsoTp`] (non-Linux stub).
158#[cfg(feature = "tokio")]
159#[derive(Debug)]
160pub struct TokioSocketCanIsoTp;
161
162#[cfg(feature = "tokio")]
163impl TokioSocketCanIsoTp {
164    pub fn open(
165        _iface: &str,
166        _rx_id: Id,
167        _tx_id: Id,
168        _options: &IsoTpKernelOptions,
169    ) -> Result<Self, Error> {
170        Err(Error)
171    }
172}
173
174#[cfg(feature = "tokio")]
175impl IsoTpAsyncEndpoint for TokioSocketCanIsoTp {
176    type Error = Error;
177
178    async fn send_to(
179        &mut self,
180        _to: u8,
181        _payload: &[u8],
182        _timeout: Duration,
183    ) -> Result<(), SendError<Self::Error>> {
184        Err(SendError::Backend(Error))
185    }
186
187    async fn send_functional_to(
188        &mut self,
189        _functional_to: u8,
190        _payload: &[u8],
191        _timeout: Duration,
192    ) -> Result<(), SendError<Self::Error>> {
193        Err(SendError::Backend(Error))
194    }
195
196    async fn recv_one<Cb>(
197        &mut self,
198        _timeout: Duration,
199        _on_payload: Cb,
200    ) -> Result<RecvStatus, RecvError<Self::Error>>
201    where
202        Cb: FnMut(RecvMeta, &[u8]) -> Result<RecvControl, Self::Error>,
203    {
204        Err(RecvError::Backend(Error))
205    }
206}
207
208#[cfg(feature = "tokio")]
209impl IsoTpAsyncEndpointRecvInto for TokioSocketCanIsoTp {
210    type Error = Error;
211
212    async fn recv_one_into(
213        &mut self,
214        _timeout: Duration,
215        _out: &mut [u8],
216    ) -> Result<RecvMetaIntoStatus, RecvError<Self::Error>> {
217        Err(RecvError::Backend(Error))
218    }
219}
220
221#[cfg(feature = "tokio")]
222impl IsoTpRxFlowControlConfig for TokioSocketCanIsoTp {
223    type Error = Error;
224
225    fn set_rx_flow_control(&mut self, _fc: RxFlowControl) -> Result<(), Self::Error> {
226        Err(Error)
227    }
228}
229
230/// Kernel-backed ISO-TP demux for UDS normal-fixed addressing (`0x18DA_TA_SA`) (non-Linux stub).
231#[derive(Debug)]
232pub struct KernelUdsDemux {
233    local_addr: u8,
234    _options: IsoTpKernelOptions,
235}
236
237impl KernelUdsDemux {
238    pub fn new(_iface: impl Into<String>, local_addr: u8, options: IsoTpKernelOptions) -> Self {
239        Self {
240            local_addr,
241            _options: options,
242        }
243    }
244
245    pub fn local_addr(&self) -> u8 {
246        self.local_addr
247    }
248
249    pub fn register_peer(&mut self, _peer: u8) -> Result<(), Error> {
250        Err(Error)
251    }
252}
253
254impl IsoTpEndpoint for KernelUdsDemux {
255    type Error = Error;
256
257    fn send_to(
258        &mut self,
259        _to: u8,
260        _payload: &[u8],
261        _timeout: Duration,
262    ) -> Result<(), SendError<Self::Error>> {
263        Err(SendError::Backend(Error))
264    }
265
266    fn send_functional_to(
267        &mut self,
268        _functional_to: u8,
269        _payload: &[u8],
270        _timeout: Duration,
271    ) -> Result<(), SendError<Self::Error>> {
272        Err(SendError::Backend(Error))
273    }
274
275    fn recv_one<Cb>(
276        &mut self,
277        _timeout: Duration,
278        _on_payload: Cb,
279    ) -> Result<RecvStatus, RecvError<Self::Error>>
280    where
281        Cb: FnMut(RecvMeta, &[u8]) -> Result<RecvControl, Self::Error>,
282    {
283        Err(RecvError::Backend(Error))
284    }
285}
286
287impl IsoTpRxFlowControlConfig for KernelUdsDemux {
288    type Error = Error;
289
290    fn set_rx_flow_control(&mut self, _fc: RxFlowControl) -> Result<(), Self::Error> {
291        Err(Error)
292    }
293}
294
295/// Kernel ISO-TP flag constants.
296pub mod flags {
297    pub const CAN_ISOTP_LISTEN_MODE: u32 = 0x0001;
298    pub const CAN_ISOTP_EXTEND_ADDR: u32 = 0x0002;
299    pub const CAN_ISOTP_TX_PADDING: u32 = 0x0004;
300    pub const CAN_ISOTP_RX_PADDING: u32 = 0x0008;
301    pub const CAN_ISOTP_CHK_PAD_LEN: u32 = 0x0010;
302    pub const CAN_ISOTP_CHK_PAD_DATA: u32 = 0x0020;
303    pub const CAN_ISOTP_HALF_DUPLEX: u32 = 0x0040;
304    pub const CAN_ISOTP_FORCE_TXSTMIN: u32 = 0x0080;
305    pub const CAN_ISOTP_FORCE_RXSTMIN: u32 = 0x0100;
306    pub const CAN_ISOTP_RX_EXT_ADDR: u32 = 0x0200;
307    pub const CAN_ISOTP_WAIT_TX_DONE: u32 = 0x0400;
308    pub const CAN_ISOTP_SF_BROADCAST: u32 = 0x0800;
309    pub const CAN_ISOTP_CF_BROADCAST: u32 = 0x1000;
310    pub const CAN_ISOTP_DYN_FC_PARMS: u32 = 0x2000;
311}