use acex_core::Vec;
use acex_sim::clock::Duration;
use acex_uds::message::DiagnosticSessionType;
pub mod periodic {
use acex_sim::clock::Duration;
pub const SLOW: Duration = Duration::from_millis(2_000);
pub const MEDIUM: Duration = Duration::from_millis(500);
pub const FAST: Duration = Duration::from_millis(50);
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct SessionConfig {
pub session_type: u8,
pub p2_timeout: Duration,
pub p2_extended_timeout: Duration,
pub s3_timeout: Duration,
}
impl SessionConfig {
pub const fn default_session() -> Self {
Self {
session_type: 0x01,
p2_timeout: Duration::from_millis(50),
p2_extended_timeout: Duration::from_millis(5_000),
s3_timeout: Duration::from_millis(5_000),
}
}
pub const fn programming_session() -> Self {
Self {
session_type: 0x02,
p2_timeout: Duration::from_millis(50),
p2_extended_timeout: Duration::from_millis(5_000),
s3_timeout: Duration::from_millis(5_000),
}
}
pub const fn extended_session() -> Self {
Self {
session_type: 0x03,
p2_timeout: Duration::from_millis(50),
p2_extended_timeout: Duration::from_millis(5_000),
s3_timeout: Duration::from_millis(5_000),
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct ServiceConfig {
pub service_id: u8,
pub supported_in: &'static [u8],
pub security_level: u8,
}
impl ServiceConfig {
pub const fn new(service_id: u8, supported_in: &'static [u8]) -> Self {
ServiceConfig {
service_id,
supported_in,
security_level: 0,
}
}
pub const fn secured(service_id: u8, supported_in: &'static [u8], security_level: u8) -> Self {
Self {
service_id,
supported_in,
security_level,
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct DidConfig {
pub identifier: u16,
pub readable_in: &'static [u8],
pub writable_in: &'static [u8],
pub security_level: u8,
pub periodic: bool,
pub min_periodic_interval: Duration,
}
impl DidConfig {
pub const fn read_only(identifier: u16, readable_in: &'static [u8]) -> Self {
Self {
identifier,
readable_in,
writable_in: &[],
security_level: 0,
periodic: false,
min_periodic_interval: Duration::from_millis(50),
}
}
pub const fn read_write(
identifier: u16,
readable_in: &'static [u8],
writable_in: &'static [u8],
) -> Self {
Self {
identifier,
readable_in,
writable_in,
security_level: 0,
periodic: false,
min_periodic_interval: Duration::from_millis(50),
}
}
pub const fn periodic(mut self, min_interval: Duration) -> Self {
self.periodic = true;
self.min_periodic_interval = min_interval;
self
}
pub const fn secured(mut self, level: u8) -> Self {
self.security_level = level;
self
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct SecurityLevelConfig {
pub level: u8,
pub max_attempts: Option<u8>,
pub lockout_duration: Option<Duration>,
pub seed_length: usize,
pub key_length: usize,
}
#[derive(Debug, Clone)]
#[cfg_attr(all(feature = "defmt", not(feature = "alloc")), derive(defmt::Format))]
pub struct ServerConfig<
const MAX_SESSIONS: usize,
const MAX_SERVICES: usize,
const MAX_DIDS: usize,
const MAX_SECURITY_LEVELS: usize,
> {
pub physical_address: u16,
pub functional_address: u16,
pub sessions: Vec<SessionConfig, MAX_SESSIONS>,
pub services: Vec<ServiceConfig, MAX_SERVICES>,
pub data_identifiers: Vec<DidConfig, MAX_DIDS>,
pub security_levels: Vec<SecurityLevelConfig, MAX_SECURITY_LEVELS>,
pub default_session_type: DiagnosticSessionType,
pub allow_read_many_dids: bool
}
impl<
const MAX_SESSIONS: usize,
const MAX_SERVICES: usize,
const MAX_DIDS: usize,
const MAX_SECURITY_LEVELS: usize,
> ServerConfig<MAX_SESSIONS, MAX_SERVICES, MAX_DIDS, MAX_SECURITY_LEVELS>
{
pub fn new(physical_address: u16, functional_address: u16) -> Self {
Self {
physical_address,
functional_address,
sessions: Vec::new(),
services: Vec::new(),
data_identifiers: Vec::new(),
security_levels: Vec::new(),
default_session_type: DiagnosticSessionType::DefaultSession,
allow_read_many_dids: false
}
}
pub fn with_session(mut self, s: SessionConfig) -> Self {
#[cfg(feature = "defmt")]
defmt::unwrap!(self.sessions.push(s));
#[cfg(not(feature = "defmt"))]
let _ = self.sessions.push(s);
self
}
pub fn with_service(mut self, s: ServiceConfig) -> Self {
#[cfg(feature = "defmt")]
defmt::unwrap!(self.services.push(s));
#[cfg(not(feature = "defmt"))]
let _ = self.services.push(s);
self
}
pub fn with_did(mut self, d: DidConfig) -> Self {
#[cfg(feature = "defmt")]
defmt::unwrap!(self.data_identifiers.push(d));
#[cfg(not(feature = "defmt"))]
let _ = self.data_identifiers.push(d);
self
}
pub fn with_security_level(mut self, l: SecurityLevelConfig) -> Self {
#[cfg(feature = "defmt")]
defmt::unwrap!(self.security_levels.push(l));
#[cfg(not(feature = "defmt"))]
let _ = self.security_levels.push(l);
self
}
pub fn with_default_session_type(mut self, session_type: DiagnosticSessionType) -> Self {
self.default_session_type = session_type;
self
}
pub fn with_allow_read_many_dids(mut self, status: bool) -> Self {
self.allow_read_many_dids = status;
self
}
pub fn find_session(&self, session_type: u8) -> Option<&SessionConfig> {
self.sessions
.iter()
.find(|s| s.session_type == session_type)
}
pub fn find_service(&self, service_id: u8) -> Option<&ServiceConfig> {
self.services.iter().find(|s| s.service_id == service_id)
}
pub fn find_did(&self, identifier: u16) -> Option<&DidConfig> {
self.data_identifiers
.iter()
.find(|d| d.identifier == identifier)
}
pub fn find_security_level(&self, level: u8) -> Option<&SecurityLevelConfig> {
self.security_levels.iter().find(|l| l.level == level)
}
pub fn service_allowed(&self, service_id: u8, session_type: u8) -> bool {
self.find_service(service_id)
.map(|s| s.supported_in.contains(&session_type))
.unwrap_or(false)
}
pub fn service_unlocked(&self, service_id: u8, security_level: u8) -> bool {
self.find_service(service_id)
.map(|s| security_level >= s.security_level)
.unwrap_or(false)
}
pub fn did_readable(&self, identifier: u16, session_type: u8) -> bool {
self.find_did(identifier)
.map(|s| s.readable_in.contains(&session_type))
.unwrap_or(false)
}
pub fn did_writable(&self, identifier: u16, session_type: u8) -> bool {
self.find_did(identifier)
.map(|s| s.writable_in.contains(&session_type))
.unwrap_or(false)
}
}