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