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