docan_rs/client/client_impl/
mod.rs1mod trait_impl;
2
3use crate::{client::context::Context, constants::LOG_TAG_CLIENT, error::DoCanError};
4use iso14229_1::{
5 request::Request,
6 response::{Code, Response},
7 DidConfig, Service, TesterPresentType, SUPPRESS_POSITIVE,
8};
9use iso15765_2::{Address, AddressType, CanIsoTp, IsoTp, IsoTpError};
10use rs_can::{CanDevice, CanFrame};
11use rsutil::types::ByteOrder;
12use std::{fmt::Display, hash::Hash};
13
14#[derive(Clone)]
15pub struct DoCanClient<D, C, F>
16where
17 D: CanDevice<Channel = C, Frame = F> + Clone + Send + Sync + 'static,
18 C: Display + Clone + Hash + Eq + Send + Sync + 'static,
19 F: CanFrame<Channel = C> + Clone + Display + Send + Sync + 'static,
20{
21 isotp: CanIsoTp<D, C, F>,
22 context: Context,
23}
24unsafe impl<D, C, F> Send for DoCanClient<D, C, F>
25where
26 D: CanDevice<Channel = C, Frame = F> + Clone + Send + Sync + 'static,
27 C: Display + Clone + Hash + Eq + Send + Sync + 'static,
28 F: CanFrame<Channel = C> + Clone + Display + Send + Sync + 'static,
29{
30}
31unsafe impl<D, C, F> Sync for DoCanClient<D, C, F>
32where
33 D: CanDevice<Channel = C, Frame = F> + Clone + Send + 'static,
34 C: Display + Clone + Hash + Eq + Send + Sync + 'static,
35 F: CanFrame<Channel = C> + Clone + Send + Display + 'static,
36{
37}
38
39impl<D, C, F> DoCanClient<D, C, F>
40where
41 D: CanDevice<Channel = C, Frame = F> + Clone + Send + 'static,
42 C: Display + Clone + Hash + Eq + Send + Sync + 'static,
43 F: CanFrame<Channel = C> + Clone + Send + Display + 'static,
44{
45 pub async fn new(
46 device: D,
47 channel: C,
48 addr: Address,
49 byte_order: ByteOrder,
50 p2_offset: Option<u16>,
51 ) -> Self {
52 Self {
53 isotp: CanIsoTp::new(device, channel, addr, false).await,
54 context: Context::new(p2_offset, byte_order),
55 }
56 }
57
58 #[inline(always)]
59 pub fn tp_layer(&mut self) -> &mut CanIsoTp<D, C, F> {
60 &mut self.isotp
61 }
62
63 #[inline(always)]
64 pub fn byte_order(&self) -> ByteOrder {
65 self.context.byte_order
66 }
67
68 fn response_service_check(response: &Response, target: Service) -> Result<bool, DoCanError> {
69 let service = response.service();
70 if response.is_negative() {
71 let nrc_code = response.nrc_code().map_err(DoCanError::Iso14229Error)?;
72 match nrc_code {
73 Code::RequestCorrectlyReceivedResponsePending => Ok(true),
74 _ => Err(DoCanError::NRCError {
75 service,
76 code: nrc_code,
77 }),
78 }
79 } else if service != target {
80 Err(DoCanError::UnexpectedResponse {
81 expect: target,
82 actual: service,
83 })
84 } else {
85 Ok(false)
86 }
87 }
88
89 async fn suppress_positive_sr(
90 &self,
91 addr_type: AddressType,
92 request: Request,
93 suppress_positive: bool,
94 cfg: &DidConfig,
95 ) -> Result<Option<Response>, DoCanError> {
96 match self.send_and_response(addr_type, request, cfg).await {
97 Ok(r) => Ok(Some(r)),
98 Err(e) => match e {
99 DoCanError::IsoTpError(e) => match e {
100 IsoTpError::Timeout { .. } => {
101 if suppress_positive {
102 Ok(None)
103 } else {
104 Err(DoCanError::IsoTpError(e))
105 }
106 }
107 _ => Err(DoCanError::IsoTpError(e)),
108 },
109 _ => Err(e),
110 },
111 }
112 }
113
114 async fn send_and_response(
115 &self,
116 addr_type: AddressType,
117 request: Request,
118 cfg: &DidConfig,
119 ) -> Result<Response, DoCanError> {
120 let service = request.service();
121 let data: Vec<_> = request.into();
122 let timing = self.context.get_session_timing().await;
123 let p2_offset = self.context.p2_offset;
124 let _ = &self
125 .isotp
126 .transmit(addr_type, data)
127 .await
128 .map_err(DoCanError::IsoTpError)?;
129
130 let data = &self
131 .isotp
132 .wait_data(timing.p2_ms() + p2_offset)
133 .await
134 .map_err(DoCanError::IsoTpError)?;
135 let mut response = Response::try_from((data, cfg)).map_err(DoCanError::Iso14229Error)?;
136 while Self::response_service_check(&response, service)? {
137 rsutil::debug!(
138 "{} tester present when {:?}",
139 LOG_TAG_CLIENT,
140 Code::RequestCorrectlyReceivedResponsePending
141 );
142 let (_, request) =
143 Self::tester_present_request(TesterPresentType::Zero, true, cfg).await?;
144 let data: Vec<_> = request.into();
145 let _ = &self
146 .isotp
147 .transmit(addr_type, data)
148 .await
149 .map_err(DoCanError::IsoTpError)?;
150
151 let data = &self
152 .isotp
153 .wait_data(timing.p2_star_ms())
154 .await
155 .map_err(DoCanError::IsoTpError)?;
156
157 response = Response::try_from((data, cfg)).map_err(DoCanError::Iso14229Error)?;
158 }
159
160 Ok(response)
161 }
162
163 fn sub_func_check(response: &Response, source: u8, service: Service) -> Result<(), DoCanError> {
164 match response.sub_function() {
165 Some(v) => {
166 let target = v.origin();
168 if target != source {
169 Err(DoCanError::UnexpectedSubFunction {
170 service,
171 expect: source,
172 actual: target,
173 })
174 } else {
175 Ok(())
176 }
177 }
178 None => Err(DoCanError::OtherError(format!(
179 "response of service `{}` got an empty sub-function",
180 service
181 ))),
182 }
183 }
184
185 #[inline(always)]
186 async fn tester_present_request(
187 test_type: TesterPresentType,
188 suppress_positive: bool,
189 did: &DidConfig,
190 ) -> Result<(Service, Request), DoCanError> {
191 let service = Service::TesterPresent;
192 let mut sub_func = test_type.into();
193 if suppress_positive {
194 sub_func |= SUPPRESS_POSITIVE;
195 }
196 let request = Request::new(service, Some(sub_func), vec![], &did)
197 .map_err(DoCanError::Iso14229Error)?;
198
199 Ok((service, request))
200 }
201}