use ace_sim::clock::Duration;
pub mod periodic {
use ace_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)]
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)]
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)]
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)]
pub struct SecurityLevelConfig {
pub level: u8,
pub max_attempts: u8,
pub lockout_duration: Duration,
pub seed_length: usize,
pub key_length: usize,
}
#[derive(Debug, Clone)]
pub struct ServerConfig {
pub physical_address: u16,
pub functional_address: u16,
pub sessions: heapless::Vec<SessionConfig, 8>,
pub services: heapless::Vec<ServiceConfig, 32>,
pub data_identifiers: heapless::Vec<DidConfig, 64>,
pub security_levels: heapless::Vec<SecurityLevelConfig, 8>,
}
impl ServerConfig {
pub fn new(physical_address: u16, functional_address: u16) -> Self {
Self {
physical_address,
functional_address,
sessions: heapless::Vec::new(),
services: heapless::Vec::new(),
data_identifiers: heapless::Vec::new(),
security_levels: heapless::Vec::new(),
}
}
pub fn with_session(mut self, s: SessionConfig) -> Self {
let _ = self.sessions.push(s);
self
}
pub fn with_service(mut self, s: ServiceConfig) -> Self {
let _ = self.services.push(s);
self
}
pub fn with_did(mut self, d: DidConfig) -> Self {
let _ = self.data_identifiers.push(d);
self
}
pub fn with_security_level(mut self, l: SecurityLevelConfig) -> Self {
let _ = self.security_levels.push(l);
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 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)
}
}