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) -> Self {
95 use socketcan::{CanFilter, SocketOptions};
96
97 let can_socket = CanSocket::open(socket).unwrap();
98 let filter = CanFilter::new(0x7F0, 0x1FFFFFFF);
99 let _ = can_socket.set_filters(&[filter]);
100 Self { can_socket }
101 }
102
103 #[cfg(target_os = "windows")]
104 pub fn new() -> Self {
105 let can_socket = match UsbCanSocket::open(UsbBus::USB1, Baudrate::Baud500K) {
106 Ok(socket) => socket,
107 Err(e) => {
108 log::warn!("The PCAN initialize failed {:?}, just open", e);
109 UsbCanSocket::open_with_usb_bus(UsbBus::USB1)
110 }
111 };
112 Self { can_socket }
113 }
114
115 pub fn split(self) -> (UdsSocketTx, UdsSocketRx) {
116 let shared_socket = Arc::new(Mutex::new(self.can_socket));
117 let rx_socket = UdsSocketRx {
118 rx: shared_socket.clone(),
119 };
120 let tx_socket = UdsSocketTx {
121 tx: shared_socket.clone(),
122 };
123 (tx_socket, rx_socket)
124 }
125}
126
127impl ErrorType for UdsSocket {
129 type Error = embedded_io_async::ErrorKind;
130}
131
132#[cfg(target_os = "linux")]
133impl Can for UdsSocket {
134 type Frame = CanFrame;
135
136 type Error = socketcan::Error;
137
138 fn transmit(&mut self, frame: &Self::Frame) -> nb::Result<Option<Self::Frame>, Self::Error> {
139 self.can_socket.transmit(frame)
140 }
141
142 fn receive(&mut self) -> nb::Result<Self::Frame, Self::Error> {
143 self.can_socket.receive()
144 }
145}
146
147#[cfg(target_os = "linux")]
148impl CanSocketTx for UdsSocketTx {
149 type Frame = CanFrame;
150 type Error = socketcan::Error;
151
152 async fn transmit(
153 &mut self,
154 frame: &Self::Frame,
155 ) -> nb::Result<Option<Self::Frame>, Self::Error> {
156 self.tx.lock().unwrap().transmit(frame)
157 }
158}
159
160#[cfg(target_os = "linux")]
161impl CanSocketRx for UdsSocketRx {
162 type Frame = CanFrame;
163 type Error = socketcan::Error;
164
165 async fn receive(&mut self) -> nb::Result<CanFrame, socketcan::Error> {
166 self.rx.lock().unwrap().receive()
167 }
168}
169
170#[cfg(target_os = "linux")]
171impl UdsSocketRx {
172 pub fn receive_with_timeout(&mut self, timeout: Duration) -> socketcan::IoResult<CanFrame> {
173 self.rx.lock().unwrap().read_frame_timeout(timeout)
174 }
175}
176
177#[cfg(target_os = "windows")]
178impl embedded_can::Error for WrappedPcanError {
179 fn kind(&self) -> embedded_can::ErrorKind {
180 match self.0 {
181 CanError::Overrun => embedded_can::ErrorKind::Overrun,
182 _ => embedded_can::ErrorKind::Other,
183 }
184 }
185}
186
187#[cfg(target_os = "windows")]
188impl embedded_can::Frame for WrappedCanFrame {
189 fn new(id: impl Into<embedded_can::Id>, data: &[u8]) -> Option<Self> {
190 let can_id: embedded_can::Id = id.into();
191 let raw_id = match can_id {
192 embedded_can::Id::Standard(standard_id) => standard_id.as_raw() as u32,
193 embedded_can::Id::Extended(extended_id) => extended_id.as_raw(),
194 };
195 match CanFrame::new(raw_id, MessageType::Extended, data) {
196 Ok(frame) => Some(WrappedCanFrame(frame)),
197 Err(_) => None,
198 }
199 }
200
201 fn id(&self) -> embedded_can::Id {
202 embedded_can::Id::Extended(ExtendedId::new(self.0.can_id()).unwrap())
203 }
204
205 fn data(&self) -> &[u8] {
206 self.0.data()
207 }
208
209 fn new_remote(id: impl Into<embedded_can::Id>, dlc: usize) -> Option<Self> {
210 let _ = dlc;
211 let _ = id;
212 todo!()
213 }
214
215 fn is_extended(&self) -> bool {
216 self.0.is_extended_frame()
217 }
218
219 fn is_remote_frame(&self) -> bool {
220 todo!()
221 }
222
223 fn dlc(&self) -> usize {
224 self.0.dlc() as usize
225 }
226
227 fn is_standard(&self) -> bool {
228 !self.0.is_extended_frame()
229 }
230
231 fn is_data_frame(&self) -> bool {
232 todo!()
233 }
234}
235
236#[cfg(target_os = "windows")]
237impl Can for UdsSocket {
238 type Frame = WrappedCanFrame;
239
240 type Error = WrappedPcanError;
241
242 fn transmit(&mut self, frame: &Self::Frame) -> nb::Result<Option<Self::Frame>, Self::Error> {
243 match self.can_socket.send(frame.0) {
244 Ok(_) => Ok(Some(Self::Frame::default())),
245 Err(e) => Err(nb::Error::Other(WrappedPcanError(e))),
246 }
247 }
248
249 fn receive(&mut self) -> nb::Result<Self::Frame, Self::Error> {
250 match self.can_socket.recv() {
251 Ok(f) => Ok(WrappedCanFrame(f.0)),
252 Err(e) => Err(nb::Error::Other(WrappedPcanError(e))),
253 }
254 }
255}
256
257#[cfg(target_os = "windows")]
258impl CanSocketTx for UdsSocketTx {
259 type Frame = WrappedCanFrame;
260
261 type Error = WrappedPcanError;
262
263 async fn transmit(
264 &mut self,
265 frame: &Self::Frame,
266 ) -> nb::Result<Option<Self::Frame>, Self::Error> {
267 match self.tx.lock().unwrap().send(frame.0) {
268 Ok(_) => Ok(Some(Self::Frame::default())),
269 Err(e) => Err(nb::Error::Other(WrappedPcanError(e))),
270 }
271 }
272}
273
274#[cfg(target_os = "windows")]
275impl CanSocketRx for UdsSocketRx {
276 type Frame = WrappedCanFrame;
277
278 type Error = WrappedPcanError;
279
280 async fn receive(&mut self) -> nb::Result<Self::Frame, Self::Error> {
281 match self.rx.lock().unwrap().recv() {
282 Ok(f) => Ok(WrappedCanFrame(f.0)),
283 Err(e) => Err(nb::Error::Other(WrappedPcanError(e))),
284 }
285 }
286}
287
288#[cfg(target_os = "windows")]
289impl UdsSocketRx {
290 pub fn receive_with_timeout(&mut self, timeout: Duration) -> Result<CanFrame, CanError> {
291 let start = chrono::Local::now();
292 while !self.rx.lock().unwrap().is_receiving()? {
293 if chrono::Local::now() > start + timeout {
294 return Err(CanError::Unknown);
295 }
296 }
297
298 self.rx.lock().unwrap().recv_frame()
299 }
300}