use super::*;
const READ_MEMORY_BY_ADDRESS_SID: u8 = 0x23;
use crate::uds::uds_definitions::SEND_RECEIVE_SID_OFFSET;
#[derive(Debug, PartialEq)]
pub struct ReadMemoryByAddressResponse {
pub data_record: Vec<u8>,
}
impl UdsClient {
pub async fn read_memory_by_address(
&self,
address_and_memory_length_format_identifier: u8,
memory_address: &[u8],
memory_size: &[u8],
) -> EcuResponseResult {
let request = formulate_request(
address_and_memory_length_format_identifier,
memory_address,
memory_size,
);
let response = self.send_and_receive(&request).await?;
parse_response(&response)
}
pub async fn read_memory_by_address_simplified(
&self,
memory_address: u64,
memory_size: u64,
memory_address_len: Option<u8>,
memory_size_len: Option<u8>,
) -> EcuResponseResult {
let request_arguments = convert_from_simple_to_normal(
memory_address,
memory_size,
memory_address_len,
memory_size_len,
)?;
self.read_memory_by_address(
request_arguments.0,
&request_arguments.1,
&request_arguments.2,
)
.await
}
}
fn convert_from_simple_to_normal(
memory_address: u64,
memory_size: u64,
memory_address_len: Option<u8>,
memory_size_len: Option<u8>,
) -> Result<(u8, Vec<u8>, Vec<u8>), UdsError> {
let mut address_encode_bytes = 0;
let mut size_encode_bytes = 0;
let mut i = memory_address;
while i > 0 {
i >>= 8;
address_encode_bytes += 1;
}
let mut i = memory_size;
while i > 0 {
i >>= 8;
size_encode_bytes += 1;
}
if let Some(mut provided_address_len) = memory_address_len {
if provided_address_len > 0x8 {
warn!(
"address_len needs to be lower or equal to 0xf, using 0xf instead of provided value"
);
provided_address_len = 0x8;
}
if provided_address_len < address_encode_bytes {
warn!("Provided address_len can not hold provided memory_address");
return Err(UdsError::InvalidArgument);
}
if provided_address_len > address_encode_bytes {
address_encode_bytes = provided_address_len;
}
}
if let Some(mut provided_memory_size_len) = memory_size_len {
if provided_memory_size_len > 0x8 {
warn!(
"memory_len needs to be lower or equal to 0xf, using 0xf instead of provided value"
);
provided_memory_size_len = 0x8;
}
if provided_memory_size_len < size_encode_bytes {
error!("Provided memory_len can not hold provided memory_size");
return Err(UdsError::InvalidArgument);
}
if provided_memory_size_len > size_encode_bytes {
size_encode_bytes = provided_memory_size_len;
}
}
let address_and_memory_length_format_identifier =
(size_encode_bytes << 4) + address_encode_bytes;
let memory_address_bytes =
memory_address.to_be_bytes().as_slice()[(8 - address_encode_bytes as usize)..].to_vec();
let memory_size_bytes =
memory_size.to_be_bytes().as_slice()[(8 - size_encode_bytes as usize)..].to_vec();
Ok((
address_and_memory_length_format_identifier,
memory_address_bytes,
memory_size_bytes,
))
}
fn formulate_request(
address_and_memory_length_format_identifier: u8,
memory_address: &[u8],
memory_size: &[u8],
) -> Vec<u8> {
let mut request: Vec<u8> = vec![
READ_MEMORY_BY_ADDRESS_SID,
address_and_memory_length_format_identifier,
];
request.extend_from_slice(memory_address);
request.extend_from_slice(memory_size);
request
}
fn parse_response(raw_response: &[u8]) -> EcuResponseResult {
let sid = raw_response[0];
if sid != READ_MEMORY_BY_ADDRESS_SID + SEND_RECEIVE_SID_OFFSET {
return Err(UdsError::SidMismatch {
expected: READ_MEMORY_BY_ADDRESS_SID + SEND_RECEIVE_SID_OFFSET,
received: sid,
raw_message: raw_response.to_owned(),
});
}
let read_memory_data = ReadMemoryByAddressResponse {
data_record: Vec::from(&raw_response[1..]),
};
let parsed_response = UdsResponse::ReadMemoryByAddress(DataFormat::Parsed(read_memory_data));
Ok(parsed_response)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ok_convert_from_simple_to_normal() {
let memory_address: u64 = 0x12345678;
let memory_size: u64 = 0x4321;
let memory_address_len: Option<u8> = None;
let memory_size_len: Option<u8> = None;
let expected: (u8, Vec<u8>, Vec<u8>) =
(0x24, vec![0x12, 0x34, 0x56, 0x78], vec![0x43, 0x21]);
let result = convert_from_simple_to_normal(
memory_address,
memory_size,
memory_address_len,
memory_size_len,
);
assert_eq!(result, Ok(expected));
}
#[test]
fn test_ok_convert_from_simple_to_normal_specified_memory_address_len() {
let memory_address: u64 = 0x5678;
let memory_size: u64 = 0x4321;
let memory_address_len: Option<u8> = Some(6);
let memory_size_len: Option<u8> = None;
let expected: (u8, Vec<u8>, Vec<u8>) =
(0x26, vec![0x0, 0x0, 0x0, 0x0, 0x56, 0x78], vec![0x43, 0x21]);
let result = convert_from_simple_to_normal(
memory_address,
memory_size,
memory_address_len,
memory_size_len,
);
assert_eq!(result, Ok(expected));
}
#[test]
fn test_ok_convert_from_simple_to_normal_specified_memory_size_len() {
let memory_address: u64 = 0x5678;
let memory_size: u64 = 0x4321;
let memory_address_len: Option<u8> = None;
let memory_size_len: Option<u8> = Some(3);
let expected: (u8, Vec<u8>, Vec<u8>) = (0x32, vec![0x56, 0x78], vec![0x0, 0x43, 0x21]);
let result = convert_from_simple_to_normal(
memory_address,
memory_size,
memory_address_len,
memory_size_len,
);
assert_eq!(result, Ok(expected));
}
#[test]
fn test_ok_convert_from_simple_to_normal_specified_both() {
let memory_address: u64 = 0x5678;
let memory_size: u64 = 0x4321;
let memory_address_len: Option<u8> = Some(4);
let memory_size_len: Option<u8> = Some(3);
let expected: (u8, Vec<u8>, Vec<u8>) =
(0x34, vec![0x0, 0x0, 0x56, 0x78], vec![0x0, 0x43, 0x21]);
let result = convert_from_simple_to_normal(
memory_address,
memory_size,
memory_address_len,
memory_size_len,
);
assert_eq!(result, Ok(expected));
}
#[test]
fn test_err_convert_from_simple_to_normal_specified_memory_address_len_too_small() {
let memory_address: u64 = 0x12345678;
let memory_size: u64 = 0x4321;
let memory_address_len: Option<u8> = Some(3);
let memory_size_len: Option<u8> = None;
let expected = UdsError::InvalidArgument;
let result = convert_from_simple_to_normal(
memory_address,
memory_size,
memory_address_len,
memory_size_len,
);
assert_eq!(result, Err(expected));
}
#[test]
fn test_err_convert_from_simple_to_normal_specified_memory_size_len_too_small() {
let memory_address: u64 = 0x12345678;
let memory_size: u64 = 0x43211234;
let memory_address_len: Option<u8> = None;
let memory_size_len: Option<u8> = Some(3);
let expected = UdsError::InvalidArgument;
let result = convert_from_simple_to_normal(
memory_address,
memory_size,
memory_address_len,
memory_size_len,
);
assert_eq!(result, Err(expected));
}
#[test]
fn test_err_convert_from_simple_to_normal_specified_memory_size_len_too_big() {
let memory_address: u64 = 0x12345678;
let memory_size: u64 = 0x43211234;
let memory_address_len: Option<u8> = None;
let memory_size_len: Option<u8> = Some(0xff);
let expected = (
0x84,
vec![0x12, 0x34, 0x56, 0x78],
vec![0x0, 0x0, 0x0, 0x0, 0x43, 0x21, 0x12, 0x34],
);
let result = convert_from_simple_to_normal(
memory_address,
memory_size,
memory_address_len,
memory_size_len,
);
assert_eq!(result, Ok(expected));
}
#[test]
fn test_err_convert_from_simple_to_normal_specified_memory_address_len_too_big() {
let memory_address: u64 = 0x12345678;
let memory_size: u64 = 0x43211234;
let memory_address_len: Option<u8> = Some(0xff);
let memory_size_len: Option<u8> = None;
let expected = (
0x48,
vec![0x0, 0x0, 0x0, 0x0, 0x12, 0x34, 0x56, 0x78],
vec![0x43, 0x21, 0x12, 0x34],
);
let result = convert_from_simple_to_normal(
memory_address,
memory_size,
memory_address_len,
memory_size_len,
);
assert_eq!(result, Ok(expected));
}
#[test]
fn test_err_convert_from_simple_to_normal_provided_address_too_big() {
let memory_address: u64 = 0x1122_3344_5566_7788;
let memory_size: u64 = 0x43211234;
let memory_address_len: Option<u8> = None;
let memory_size_len: Option<u8> = None;
let expected = (
0x48,
vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88],
vec![0x43, 0x21, 0x12, 0x34],
);
let result = convert_from_simple_to_normal(
memory_address,
memory_size,
memory_address_len,
memory_size_len,
);
assert_eq!(result, Ok(expected));
}
#[test]
fn test_err_convert_from_simple_to_normal_provided_size_too_big() {
let memory_address: u64 = 0x1122;
let memory_size: u64 = 0x1122_3344_5566_7788;
let memory_address_len: Option<u8> = None;
let memory_size_len: Option<u8> = None;
let expected = (
0x82,
vec![0x11, 0x22],
vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88],
);
let result = convert_from_simple_to_normal(
memory_address,
memory_size,
memory_address_len,
memory_size_len,
);
assert_eq!(result, Ok(expected));
}
#[test]
fn test_ok_compose_request() {
let address_and_memory_length_format_identifier: u8 = 0x24;
let memory_address: [u8; 4] = [0x4, 0x32, 0x12, 0x1];
let memory_size: [u8; 2] = [0x1, 0x12];
let expected = vec![
READ_MEMORY_BY_ADDRESS_SID,
0x24,
0x4,
0x32,
0x12,
0x1,
0x1,
0x12,
];
let result = formulate_request(
address_and_memory_length_format_identifier,
&memory_address,
&memory_size,
);
assert_eq!(result, expected);
}
#[test]
fn test_ok_parse_response() {
let sid = READ_MEMORY_BY_ADDRESS_SID + SEND_RECEIVE_SID_OFFSET;
let data = vec![sid, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let expected =
UdsResponse::ReadMemoryByAddress(DataFormat::Parsed(ReadMemoryByAddressResponse {
data_record: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
}));
let result = parse_response(&data);
assert_eq!(result, Ok(expected));
}
}