docan_rs/client/client_impl/
mod.rs

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