uds_rs/uds/
read_memory_by_address.rs

1//! # Implementation of ReadMemoryByAddress 0x23 service
2//!
3//! This module provides following methods for UdsClient:
4//!
5//! [UdsClient::read_memory_by_address]  
6//! [UdsClient::read_memory_by_address_simplified]  
7//!
8//! Main reason for existence of simplified method is address_and_memory_length_format_identifier
9//! argument which can be derived from other entered arguments. However it can have some benefit
10//! to have this function to choose size manually, that is why simplified version is not the default.
11
12use super::*;
13
14const READ_MEMORY_BY_ADDRESS_SID: u8 = 0x23;
15use crate::uds::uds_definitions::SEND_RECEIVE_SID_OFFSET;
16
17#[derive(Debug, PartialEq)]
18pub struct ReadMemoryByAddressResponse {
19    data_record: Vec<u8>,
20}
21
22impl UdsClient {
23    /// address_and_memory_length_format_identifier (explained in ISOTP table 152)
24    /// is two values encoded in single message - could be split into two separate
25    /// values mem_length and address_length. Or create wrapper, that would take two parameters.
26    ///
27    /// Or could be even more simplified, by accepting just address and mem_size values, but that
28    /// would be less flexible
29    ///
30    /// Takes memory address and byte size encoded in u8 slice. MSB is at position 0.
31    /// Examples are shown in ISOTP documentation chapter 10.3.5.2
32    pub async fn read_memory_by_address(
33        &self,
34        address_and_memory_length_format_identifier: u8,
35        memory_address: &[u8],
36        memory_size: &[u8],
37    ) -> EcuResponseResult {
38        let request = formulate_request(
39            address_and_memory_length_format_identifier,
40            memory_address,
41            memory_size,
42        );
43        let response = self.send_and_receive(&request).await?;
44        let parsed_response = parse_response(&response);
45        return parsed_response;
46    }
47    /// Simplified method, where address_and_memory_length_format_identifier will be assumed from
48    /// provided arguments if not specified.
49    /// If assumption will take place, the lowest possible size will be used.
50    pub async fn read_memory_by_address_simplified(
51        &self,
52        memory_address: u64,
53        memory_size: u64,
54        memory_address_len: Option<u8>,
55        memory_size_len: Option<u8>,
56    ) -> EcuResponseResult {
57        let request_arguments = convert_from_simple_to_normal(
58            memory_address,
59            memory_size,
60            memory_address_len,
61            memory_size_len,
62        )?;
63
64        self.read_memory_by_address(
65            request_arguments.0,
66            &request_arguments.1,
67            &request_arguments.2,
68        )
69        .await
70    }
71}
72
73fn convert_from_simple_to_normal(
74    memory_address: u64,
75    memory_size: u64,
76    memory_address_len: Option<u8>,
77    memory_size_len: Option<u8>,
78) -> Result<(u8, Vec<u8>, Vec<u8>), UdsError> {
79    let mut address_encode_bytes = 0;
80    let mut size_encode_bytes = 0;
81
82    let mut i = memory_address;
83    while i > 0 {
84        i = i >> 8;
85        address_encode_bytes += 1;
86    }
87    let mut i = memory_size;
88    while i > 0 {
89        i = i >> 8;
90        size_encode_bytes += 1;
91    }
92
93    if let Some(mut provided_address_len) = memory_address_len {
94        if provided_address_len > 0x8 {
95            warn!("address_len needs to be lower or equal to 0xf, using 0xf instead of provided value");
96            provided_address_len = 0x8;
97        }
98
99        if provided_address_len < address_encode_bytes {
100            warn!("Provided address_len can not hold provided memory_address");
101            return Err(UdsError::InvalidArgument);
102        }
103        if provided_address_len > address_encode_bytes {
104            address_encode_bytes = provided_address_len;
105        }
106    }
107    if let Some(mut provided_memory_size_len) = memory_size_len {
108        if provided_memory_size_len > 0x8 {
109            warn!(
110                "memory_len needs to be lower or equal to 0xf, using 0xf instead of provided value"
111            );
112            provided_memory_size_len = 0x8;
113        }
114        if provided_memory_size_len < size_encode_bytes {
115            error!("Provided memory_len can not hold provided memory_size");
116            return Err(UdsError::InvalidArgument);
117        }
118        if provided_memory_size_len > size_encode_bytes {
119            size_encode_bytes = provided_memory_size_len;
120        }
121    }
122    let address_and_memory_length_format_identifier =
123        (size_encode_bytes << 4) + address_encode_bytes;
124
125    // magic to convert [u8; 8] into [u8; encode_size] by dropping first 8-encode_bytes bytes
126    let memory_address_bytes =
127        memory_address.to_be_bytes().as_slice()[(8 - address_encode_bytes as usize)..].to_vec();
128    let memory_size_bytes =
129        memory_size.to_be_bytes().as_slice()[(8 - size_encode_bytes as usize)..].to_vec();
130    Ok((
131        address_and_memory_length_format_identifier,
132        memory_address_bytes,
133        memory_size_bytes,
134    ))
135}
136
137fn formulate_request(
138    address_and_memory_length_format_identifier: u8,
139    memory_address: &[u8],
140    memory_size: &[u8],
141) -> Vec<u8> {
142    let mut request: Vec<u8> = vec![
143        READ_MEMORY_BY_ADDRESS_SID,
144        address_and_memory_length_format_identifier,
145    ];
146    request.extend_from_slice(memory_address);
147    request.extend_from_slice(memory_size);
148
149    request
150}
151fn parse_response(raw_response: &[u8]) -> EcuResponseResult {
152    let sid = raw_response[0];
153    if sid != READ_MEMORY_BY_ADDRESS_SID + SEND_RECEIVE_SID_OFFSET {
154        return Err(UdsError::SidMismatch {
155            expected: READ_MEMORY_BY_ADDRESS_SID + SEND_RECEIVE_SID_OFFSET,
156            received: sid,
157            raw_message: raw_response.to_owned(),
158        });
159    }
160    let read_memory_data = ReadMemoryByAddressResponse {
161        data_record: Vec::from(&raw_response[1..]),
162    };
163    let parsed_response = UdsResponse::ReadMemoryByAddress(DataFormat::Parsed(read_memory_data));
164    Ok(parsed_response)
165}
166
167#[cfg(test)]
168mod tests {
169    use super::*;
170
171    #[test]
172    fn test_ok_convert_from_simple_to_normal() {
173        let memory_address: u64 = 0x12345678;
174        let memory_size: u64 = 0x4321;
175        let memory_address_len: Option<u8> = None;
176        let memory_size_len: Option<u8> = None;
177        let expected: (u8, Vec<u8>, Vec<u8>) =
178            (0x24, vec![0x12, 0x34, 0x56, 0x78], vec![0x43, 0x21]);
179        let result = convert_from_simple_to_normal(
180            memory_address,
181            memory_size,
182            memory_address_len,
183            memory_size_len,
184        );
185        assert_eq!(result, Ok(expected));
186    }
187
188    #[test]
189    fn test_ok_convert_from_simple_to_normal_specified_memory_address_len() {
190        let memory_address: u64 = 0x5678;
191        let memory_size: u64 = 0x4321;
192        let memory_address_len: Option<u8> = Some(6);
193        let memory_size_len: Option<u8> = None;
194        let expected: (u8, Vec<u8>, Vec<u8>) =
195            (0x26, vec![0x0, 0x0, 0x0, 0x0, 0x56, 0x78], vec![0x43, 0x21]);
196        let result = convert_from_simple_to_normal(
197            memory_address,
198            memory_size,
199            memory_address_len,
200            memory_size_len,
201        );
202        assert_eq!(result, Ok(expected));
203    }
204
205    #[test]
206    fn test_ok_convert_from_simple_to_normal_specified_memory_size_len() {
207        let memory_address: u64 = 0x5678;
208        let memory_size: u64 = 0x4321;
209        let memory_address_len: Option<u8> = None;
210        let memory_size_len: Option<u8> = Some(3);
211        let expected: (u8, Vec<u8>, Vec<u8>) = (0x32, vec![0x56, 0x78], vec![0x0, 0x43, 0x21]);
212        let result = convert_from_simple_to_normal(
213            memory_address,
214            memory_size,
215            memory_address_len,
216            memory_size_len,
217        );
218        assert_eq!(result, Ok(expected));
219    }
220
221    #[test]
222    fn test_ok_convert_from_simple_to_normal_specified_both() {
223        let memory_address: u64 = 0x5678;
224        let memory_size: u64 = 0x4321;
225        let memory_address_len: Option<u8> = Some(4);
226        let memory_size_len: Option<u8> = Some(3);
227        let expected: (u8, Vec<u8>, Vec<u8>) =
228            (0x34, vec![0x0, 0x0, 0x56, 0x78], vec![0x0, 0x43, 0x21]);
229        let result = convert_from_simple_to_normal(
230            memory_address,
231            memory_size,
232            memory_address_len,
233            memory_size_len,
234        );
235        assert_eq!(result, Ok(expected));
236    }
237
238    #[test]
239    fn test_err_convert_from_simple_to_normal_specified_memory_address_len_too_small() {
240        let memory_address: u64 = 0x12345678;
241        let memory_size: u64 = 0x4321;
242        let memory_address_len: Option<u8> = Some(3);
243        let memory_size_len: Option<u8> = None;
244        let expected = UdsError::InvalidArgument;
245        let result = convert_from_simple_to_normal(
246            memory_address,
247            memory_size,
248            memory_address_len,
249            memory_size_len,
250        );
251        assert_eq!(result, Err(expected));
252    }
253
254    #[test]
255    fn test_err_convert_from_simple_to_normal_specified_memory_size_len_too_small() {
256        let memory_address: u64 = 0x12345678;
257        let memory_size: u64 = 0x43211234;
258        let memory_address_len: Option<u8> = None;
259        let memory_size_len: Option<u8> = Some(3);
260        let expected = UdsError::InvalidArgument;
261        let result = convert_from_simple_to_normal(
262            memory_address,
263            memory_size,
264            memory_address_len,
265            memory_size_len,
266        );
267        assert_eq!(result, Err(expected));
268    }
269    #[test]
270    fn test_err_convert_from_simple_to_normal_specified_memory_size_len_too_big() {
271        let memory_address: u64 = 0x12345678;
272        let memory_size: u64 = 0x43211234;
273        let memory_address_len: Option<u8> = None;
274        let memory_size_len: Option<u8> = Some(0xff);
275        let expected = (
276            0x84,
277            vec![0x12, 0x34, 0x56, 0x78],
278            vec![0x0, 0x0, 0x0, 0x0, 0x43, 0x21, 0x12, 0x34],
279        );
280        let result = convert_from_simple_to_normal(
281            memory_address,
282            memory_size,
283            memory_address_len,
284            memory_size_len,
285        );
286        assert_eq!(result, Ok(expected));
287    }
288    #[test]
289    fn test_err_convert_from_simple_to_normal_specified_memory_address_len_too_big() {
290        let memory_address: u64 = 0x12345678;
291        let memory_size: u64 = 0x43211234;
292        let memory_address_len: Option<u8> = Some(0xff);
293        let memory_size_len: Option<u8> = None;
294        let expected = (
295            0x48,
296            vec![0x0, 0x0, 0x0, 0x0, 0x12, 0x34, 0x56, 0x78],
297            vec![0x43, 0x21, 0x12, 0x34],
298        );
299        let result = convert_from_simple_to_normal(
300            memory_address,
301            memory_size,
302            memory_address_len,
303            memory_size_len,
304        );
305        assert_eq!(result, Ok(expected));
306    }
307    #[test]
308    fn test_err_convert_from_simple_to_normal_provided_address_too_big() {
309        let memory_address: u64 = 0x1122_3344_5566_7788;
310        let memory_size: u64 = 0x43211234;
311        let memory_address_len: Option<u8> = None;
312        let memory_size_len: Option<u8> = None;
313        let expected = (
314            0x48,
315            vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88],
316            vec![0x43, 0x21, 0x12, 0x34],
317        );
318        let result = convert_from_simple_to_normal(
319            memory_address,
320            memory_size,
321            memory_address_len,
322            memory_size_len,
323        );
324
325        assert_eq!(result, Ok(expected));
326    }
327    #[test]
328    fn test_err_convert_from_simple_to_normal_provided_size_too_big() {
329        let memory_address: u64 = 0x1122;
330        let memory_size: u64 = 0x1122_3344_5566_7788;
331        let memory_address_len: Option<u8> = None;
332        let memory_size_len: Option<u8> = None;
333        let expected = (
334            0x82,
335            vec![0x11, 0x22],
336            vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88],
337        );
338        let result = convert_from_simple_to_normal(
339            memory_address,
340            memory_size,
341            memory_address_len,
342            memory_size_len,
343        );
344        assert_eq!(result, Ok(expected));
345    }
346    #[test]
347    fn test_ok_compose_request() {
348        let address_and_memory_length_format_identifier: u8 = 0x24;
349        let memory_address: [u8; 4] = [0x4, 0x32, 0x12, 0x1];
350        let memory_size: [u8; 2] = [0x1, 0x12];
351        let expected = vec![
352            READ_MEMORY_BY_ADDRESS_SID,
353            0x24,
354            0x4,
355            0x32,
356            0x12,
357            0x1,
358            0x1,
359            0x12,
360        ];
361        let result = formulate_request(
362            address_and_memory_length_format_identifier,
363            &memory_address,
364            &memory_size,
365        );
366        assert_eq!(result, expected);
367    }
368    #[test]
369    fn test_ok_parse_response() {
370        let sid = READ_MEMORY_BY_ADDRESS_SID + SEND_RECEIVE_SID_OFFSET;
371        let data = vec![sid, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
372        let expected =
373            UdsResponse::ReadMemoryByAddress(DataFormat::Parsed(ReadMemoryByAddressResponse {
374                data_record: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
375            }));
376        let result = parse_response(&data);
377        assert_eq!(result, Ok(expected));
378    }
379}