uds_client/socket_can/
mod.rs

1#[cfg(target_os = "windows")]
2use embedded_can::ExtendedId;
3use embedded_can::{Frame, nb::Can};
4use embedded_io_async::ErrorType;
5#[cfg(target_os = "windows")]
6use peak_can::{
7    bus::UsbBus,
8    df::ReceiveStatus,
9    error::CanError,
10    socket::usb::UsbCanSocket,
11    socket::{Baudrate, RecvCan, SendCan},
12    socket::{CanFrame, MessageType},
13};
14#[cfg(target_os = "linux")]
15use socketcan::{CanFrame, CanSocket, Socket};
16use std::{
17    sync::{Arc, Mutex},
18    time::Duration,
19};
20
21#[cfg(target_os = "windows")]
22#[derive(Default, Clone, Copy)]
23pub struct WrappedCanFrame(pub CanFrame);
24#[cfg(target_os = "windows")]
25#[derive(Debug)]
26pub struct WrappedPcanError(pub CanError);
27
28pub trait CanSocketTx {
29    /// Associated frame type.
30    type Frame: Frame;
31
32    /// Associated error type.
33    type Error: embedded_can::Error;
34
35    // The transmit function
36    fn transmit(&mut self, frame: &Self::Frame) -> nb::Result<Option<Self::Frame>, Self::Error>;
37}
38
39#[allow(dead_code)]
40pub trait CanSocketRx {
41    /// Associated frame type.
42    type Frame: Frame;
43
44    /// Associated error type.
45    type Error: embedded_can::Error;
46
47    // The receive function
48    fn receive(&mut self) -> nb::Result<Self::Frame, Self::Error>;
49}
50
51pub struct UdsSocket {
52    #[cfg(target_os = "linux")]
53    can_socket: CanSocket,
54    #[cfg(target_os = "windows")]
55    can_socket: UsbCanSocket,
56}
57
58pub struct UdsSocketTx {
59    #[cfg(target_os = "linux")]
60    tx: Arc<Mutex<CanSocket>>,
61    #[cfg(target_os = "windows")]
62    tx: Arc<Mutex<UsbCanSocket>>,
63}
64
65pub struct UdsSocketRx {
66    #[cfg(target_os = "linux")]
67    rx: Arc<Mutex<CanSocket>>,
68    #[cfg(target_os = "windows")]
69    rx: Arc<Mutex<UsbCanSocket>>,
70}
71
72impl UdsSocket {
73    #[cfg(target_os = "linux")]
74    pub fn new(socket: &str) -> Self {
75        use socketcan::{CanFilter, SocketOptions};
76
77        let can_socket = CanSocket::open(socket).unwrap();
78        let filter = CanFilter::new(0x7F0, 0x1FFFFFFF);
79        let _ = can_socket.set_filters(&[filter]);
80        Self { can_socket }
81    }
82
83    #[cfg(target_os = "windows")]
84    pub fn new() -> Self {
85        let can_socket = match UsbCanSocket::open(UsbBus::USB1, Baudrate::Baud500K) {
86            Ok(socket) => socket,
87            Err(e) => {
88                log::warn!("The PCAN initialize failed {:?}, just open", e);
89                UsbCanSocket::open_with_usb_bus(UsbBus::USB1)
90            }
91        };
92        Self { can_socket }
93    }
94
95    pub fn split(self) -> (UdsSocketTx, UdsSocketRx) {
96        let shared_socket = Arc::new(Mutex::new(self.can_socket));
97        let rx_socket = UdsSocketRx {
98            rx: shared_socket.clone(),
99        };
100        let tx_socket = UdsSocketTx {
101            tx: shared_socket.clone(),
102        };
103        (tx_socket, rx_socket)
104    }
105}
106
107// Specify the error type for `embedded_io_async`
108impl ErrorType for UdsSocket {
109    type Error = embedded_io_async::ErrorKind;
110}
111
112#[cfg(target_os = "linux")]
113impl Can for UdsSocket {
114    type Frame = CanFrame;
115
116    type Error = socketcan::Error;
117
118    fn transmit(&mut self, frame: &Self::Frame) -> nb::Result<Option<Self::Frame>, Self::Error> {
119        self.can_socket.transmit(frame)
120    }
121
122    fn receive(&mut self) -> nb::Result<Self::Frame, Self::Error> {
123        self.can_socket.receive()
124    }
125}
126
127#[cfg(target_os = "linux")]
128impl CanSocketTx for UdsSocketTx {
129    type Frame = CanFrame;
130    type Error = socketcan::Error;
131
132    fn transmit(&mut self, frame: &Self::Frame) -> nb::Result<Option<Self::Frame>, Self::Error> {
133        self.tx.lock().unwrap().transmit(frame)
134    }
135}
136
137#[cfg(target_os = "linux")]
138impl CanSocketRx for UdsSocketRx {
139    type Frame = CanFrame;
140    type Error = socketcan::Error;
141
142    fn receive(&mut self) -> nb::Result<CanFrame, socketcan::Error> {
143        self.rx.lock().unwrap().receive()
144    }
145}
146
147#[cfg(target_os = "linux")]
148impl UdsSocketRx {
149    pub fn receive_with_timeout(&mut self, timeout: Duration) -> socketcan::IoResult<CanFrame> {
150        self.rx.lock().unwrap().read_frame_timeout(timeout)
151    }
152}
153
154#[cfg(target_os = "windows")]
155impl embedded_can::Error for WrappedPcanError {
156    fn kind(&self) -> embedded_can::ErrorKind {
157        match self.0 {
158            CanError::Overrun => embedded_can::ErrorKind::Overrun,
159            _ => embedded_can::ErrorKind::Other,
160        }
161    }
162}
163
164#[cfg(target_os = "windows")]
165impl embedded_can::Frame for WrappedCanFrame {
166    fn new(id: impl Into<embedded_can::Id>, data: &[u8]) -> Option<Self> {
167        let can_id: embedded_can::Id = id.into();
168        let raw_id = match can_id {
169            embedded_can::Id::Standard(standard_id) => standard_id.as_raw() as u32,
170            embedded_can::Id::Extended(extended_id) => extended_id.as_raw(),
171        };
172        match CanFrame::new(raw_id, MessageType::Extended, data) {
173            Ok(frame) => Some(WrappedCanFrame(frame)),
174            Err(_) => None,
175        }
176    }
177
178    fn id(&self) -> embedded_can::Id {
179        embedded_can::Id::Extended(ExtendedId::new(self.0.can_id()).unwrap())
180    }
181
182    fn data(&self) -> &[u8] {
183        self.0.data()
184    }
185
186    fn new_remote(id: impl Into<embedded_can::Id>, dlc: usize) -> Option<Self> {
187        let _ = dlc;
188        let _ = id;
189        todo!()
190    }
191
192    fn is_extended(&self) -> bool {
193        self.0.is_extended_frame()
194    }
195
196    fn is_remote_frame(&self) -> bool {
197        todo!()
198    }
199
200    fn dlc(&self) -> usize {
201        self.0.dlc() as usize
202    }
203
204    fn is_standard(&self) -> bool {
205        !self.0.is_extended_frame()
206    }
207
208    fn is_data_frame(&self) -> bool {
209        todo!()
210    }
211}
212
213#[cfg(target_os = "windows")]
214impl Can for UdsSocket {
215    type Frame = WrappedCanFrame;
216
217    type Error = WrappedPcanError;
218
219    fn transmit(&mut self, frame: &Self::Frame) -> nb::Result<Option<Self::Frame>, Self::Error> {
220        match self.can_socket.send(frame.0) {
221            Ok(_) => Ok(Some(Self::Frame::default())),
222            Err(e) => Err(nb::Error::Other(WrappedPcanError(e))),
223        }
224    }
225
226    fn receive(&mut self) -> nb::Result<Self::Frame, Self::Error> {
227        match self.can_socket.recv() {
228            Ok(f) => Ok(WrappedCanFrame(f.0)),
229            Err(e) => Err(nb::Error::Other(WrappedPcanError(e))),
230        }
231    }
232}
233
234#[cfg(target_os = "windows")]
235impl CanSocketTx for UdsSocketTx {
236    type Frame = WrappedCanFrame;
237
238    type Error = WrappedPcanError;
239
240    fn transmit(&mut self, frame: &Self::Frame) -> nb::Result<Option<Self::Frame>, Self::Error> {
241        match self.tx.lock().unwrap().send(frame.0) {
242            Ok(_) => Ok(Some(Self::Frame::default())),
243            Err(e) => Err(nb::Error::Other(WrappedPcanError(e))),
244        }
245    }
246}
247
248#[cfg(target_os = "windows")]
249impl CanSocketRx for UdsSocketRx {
250    type Frame = WrappedCanFrame;
251
252    type Error = WrappedPcanError;
253
254    fn receive(&mut self) -> nb::Result<Self::Frame, Self::Error> {
255        match self.rx.lock().unwrap().recv() {
256            Ok(f) => Ok(WrappedCanFrame(f.0)),
257            Err(e) => Err(nb::Error::Other(WrappedPcanError(e))),
258        }
259    }
260}
261
262#[cfg(target_os = "windows")]
263impl UdsSocketRx {
264    pub fn receive_with_timeout(&mut self, timeout: Duration) -> Result<CanFrame, CanError> {
265        let start = chrono::Local::now();
266        while !self.rx.lock().unwrap().is_receiving()? {
267            if chrono::Local::now() > start + timeout {
268                return Err(CanError::Unknown);
269            }
270        }
271
272        self.rx.lock().unwrap().recv_frame()
273    }
274}