#![allow(unused_imports, clippy::non_minimal_cfg)]
mod session_ctrl; pub use session_ctrl::*;
mod ecu_reset; pub use ecu_reset::*;
mod security_access; pub use security_access::*;
mod communication_ctrl; pub use communication_ctrl::*;
#[cfg(any(feature = "std2020"))]
mod authentication; #[cfg(any(feature = "std2020"))]
pub use authentication::*;
mod tester_present; pub use tester_present::*;
#[cfg(any(feature = "std2006", feature = "std2013"))] mod access_timing_param; #[cfg(any(feature = "std2006", feature = "std2013"))] pub use access_timing_param::*;
mod secured_data_trans; pub use secured_data_trans::*;
mod ctrl_dtc_setting; pub use ctrl_dtc_setting::*;
mod response_on_event; pub use response_on_event::*;
mod link_ctrl; pub use link_ctrl::*;
mod read_did; pub use read_did::*;
mod read_mem_by_addr; pub use read_mem_by_addr::*;
mod read_scaling_did; pub use read_scaling_did::*;
mod read_data_by_pid; pub use read_data_by_pid::*;
mod dynamically_define_did; pub use dynamically_define_did::*;
mod write_did; pub use write_did::*;
mod write_mem_by_addr; pub use write_mem_by_addr::*;
mod clear_diagnostic_info; pub use clear_diagnostic_info::*;
mod read_dtc_info; pub use read_dtc_info::*;
mod io_ctrl; pub use io_ctrl::*;
mod routine_ctrl; pub use routine_ctrl::*;
mod request_download; pub use request_download::*;
mod request_upload; pub use request_upload::*;
mod transfer_data; pub use transfer_data::*;
mod request_transfer_exit; pub use request_transfer_exit::*;
#[cfg(any(feature = "std2013", feature = "std2020"))]
mod request_file_transfer; #[cfg(any(feature = "std2013", feature = "std2020"))]
pub use request_file_transfer::*;
use crate::{error::Error, request, utils, Configuration, RequestData, Service, SUPPRESS_POSITIVE};
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct SubFunction {
pub(crate) function: u8,
suppress_positive: bool,
}
impl SubFunction {
pub fn new(function: u8, suppress_positive: bool) -> Self {
Self {
function,
suppress_positive,
}
}
#[inline]
pub fn function<T: TryFrom<u8, Error = Error>>(&self) -> Result<T, Error> {
T::try_from(self.function)
}
#[inline]
pub const fn is_suppress_positive(&self) -> bool {
self.suppress_positive
}
}
impl From<SubFunction> for u8 {
fn from(val: SubFunction) -> Self {
let mut result = val.function;
if val.suppress_positive {
result |= SUPPRESS_POSITIVE;
}
result
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Request {
pub(crate) service: Service,
pub(crate) sub_func: Option<SubFunction>,
pub(crate) data: Vec<u8>,
}
impl Request {
pub fn new<T: AsRef<[u8]>>(
service: Service,
sub_func: Option<u8>,
data: T,
cfg: &Configuration,
) -> Result<Self, Error> {
match service {
Service::SessionCtrl => SessionCtrl::new_request(data, sub_func, cfg),
Service::ECUReset => ECUReset::new_request(data, sub_func, cfg),
Service::ClearDiagnosticInfo => ClearDiagnosticInfo::new_request(data, sub_func, cfg),
Service::ReadDTCInfo => DTCInfo::new_request(data, sub_func, cfg),
Service::ReadDID => ReadDID::new_request(data, sub_func, cfg),
Service::ReadMemByAddr => ReadMemByAddr::new_request(data, sub_func, cfg),
Service::ReadScalingDID => ReadScalingDID::new_request(data, sub_func, cfg),
Service::SecurityAccess => SecurityAccess::new_request(data, sub_func, cfg),
Service::CommunicationCtrl => CommunicationCtrl::new_request(data, sub_func, cfg),
#[cfg(any(feature = "std2020"))]
Service::Authentication => Authentication::new_request(data, sub_func, cfg),
Service::ReadDataByPeriodId => ReadDataByPeriodId::new_request(data, sub_func, cfg),
Service::DynamicalDefineDID => DynamicallyDefineDID::new_request(data, sub_func, cfg),
Service::WriteDID => WriteDID::new_request(data, sub_func, cfg),
Service::IOCtrl => IOCtrl::new_request(data, sub_func, cfg),
Service::RoutineCtrl => RoutineCtrl::new_request(data, sub_func, cfg),
Service::RequestDownload => RequestDownload::new_request(data, sub_func, cfg),
Service::RequestUpload => RequestUpload::new_request(data, sub_func, cfg),
Service::TransferData => TransferData::new_request(data, sub_func, cfg),
Service::RequestTransferExit => RequestTransferExit::new_request(data, sub_func, cfg),
#[cfg(any(feature = "std2013", feature = "std2020"))]
Service::RequestFileTransfer => RequestFileTransfer::new_request(data, sub_func, cfg),
Service::WriteMemByAddr => WriteMemByAddr::new_request(data, sub_func, cfg),
Service::TesterPresent => TesterPresent::new_request(data, sub_func, cfg),
#[cfg(any(feature = "std2006", feature = "std2013"))]
Service::AccessTimingParam => AccessTimingParameter::new_request(data, sub_func, cfg),
Service::SecuredDataTrans => SecuredDataTrans::new_request(data, sub_func, cfg),
Service::CtrlDTCSetting => CtrlDTCSetting::new_request(data, sub_func, cfg),
Service::ResponseOnEvent => ResponseOnEvent::new_request(data, sub_func, cfg),
Service::LinkCtrl => LinkCtrl::new_request(data, sub_func, cfg),
Service::NRC => Err(Error::OtherError("got an NRC service from request".into())),
}
}
#[inline]
pub fn service(&self) -> Service {
self.service
}
#[inline]
pub fn sub_function(&self) -> Option<SubFunction> {
self.sub_func
}
#[inline]
pub fn raw_data(&self) -> &[u8] {
self.data.as_slice()
}
#[inline]
pub fn data<T>(&self, cfg: &Configuration) -> Result<T, Error>
where
T: RequestData,
{
T::try_from((self, cfg))
}
#[inline]
fn new_sub_func<T: AsRef<[u8]>>(
data: T,
service: Service,
cfg: &Configuration,
) -> Result<Self, Error> {
let data = data.as_ref();
let data_len = data.len();
let mut offset = 0;
utils::data_length_check(data_len, offset + 1, false)?;
let sub_func = data[offset];
offset += 1;
let data = data[offset..].to_vec();
Request::new(service, Some(sub_func), data, cfg)
}
}
impl From<Request> for Vec<u8> {
fn from(mut val: Request) -> Self {
let mut result = vec![val.service.into()];
if let Some(sub_func) = val.sub_func {
result.push(sub_func.into());
}
result.append(&mut val.data);
result
}
}
impl<T: AsRef<[u8]>> TryFrom<(Service, T, &Configuration)> for Request {
type Error = Error;
fn try_from((service, data, cfg): (Service, T, &Configuration)) -> Result<Self, Self::Error> {
match service {
Service::SessionCtrl
| Service::ECUReset
| Service::SecurityAccess
| Service::CommunicationCtrl
| Service::ReadDTCInfo
| Service::RoutineCtrl
| Service::CtrlDTCSetting
| Service::TesterPresent
| Service::LinkCtrl
| Service::DynamicalDefineDID => Self::new_sub_func(data, service, cfg),
#[cfg(any(feature = "std2006", feature = "std2013"))]
Service::AccessTimingParam => Self::new_sub_func(data, service, cfg),
#[cfg(any(feature = "std2020"))]
Service::Authentication => Self::new_sub_func(data, service, cfg),
#[cfg(any(feature = "std2013", feature = "std2020"))]
Service::RequestFileTransfer => Self::new_sub_func(data, service, cfg),
Service::ClearDiagnosticInfo
| Service::ReadDID
| Service::ReadMemByAddr
| Service::ReadScalingDID
| Service::ReadDataByPeriodId
| Service::WriteDID
| Service::IOCtrl
| Service::RequestDownload
| Service::RequestUpload
| Service::TransferData
| Service::RequestTransferExit
| Service::WriteMemByAddr
| Service::SecuredDataTrans
| Service::ResponseOnEvent => Self::new(service, None, data, cfg),
Service::NRC => Err(Error::OtherError("got an NRC service from request".into())),
}
}
}
impl<T: AsRef<[u8]>> TryFrom<(T, &Configuration)> for Request {
type Error = Error;
fn try_from((data, cfg): (T, &Configuration)) -> Result<Self, Self::Error> {
let data = data.as_ref();
let data_len = data.len();
utils::data_length_check(data_len, 1, false)?;
let mut offset = 0;
let service = Service::try_from(data[offset])?;
offset += 1;
Self::try_from((service, &data[offset..], cfg))
}
}