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