use std::future::pending;
use std::vec::Vec;
use uom::si::power::watt;
use usbpd_traits::Driver;
use crate::protocol_layer::message::data::request::EprRequestDataObject;
use crate::protocol_layer::message::data::source_capabilities::{
Augmented, FixedSupply, PowerDataObject, SprProgrammablePowerSupply,
};
use crate::sink::device_policy_manager::DevicePolicyManager as SinkDevicePolicyManager;
use crate::timers::Timer;
use crate::units::Power;
pub const DUMMY_SPR_CAPS_EPR_CAPABLE: [u8; 26] = [
0xA1, 0x61, 0x2C, 0x91, 0x91, 0x0A, 0x2C, 0xD1, 0x12, 0x00, 0x2C, 0xC1, 0x13, 0x00, 0x2C, 0xB1, 0x14, 0x00, 0xF4,
0x41, 0x16, 0x00, 0x64, 0x32, 0xA4, 0xC9,
];
pub const DUMMY_EPR_SOURCE_CAPS_CHUNK_0: [u8; 30] = [
0xB1, 0xFD, 0x28, 0x80, 0x2C, 0x91, 0x91, 0x0A, 0x2C, 0xD1, 0x12, 0x00, 0x2C, 0xC1, 0x13, 0x00, 0x2C, 0xB1, 0x14,
0x00, 0xF4, 0x41, 0x16, 0x00, 0x64, 0x32, 0xA4, 0xC9, 0x00, 0x00,
];
pub const DUMMY_EPR_SOURCE_CAPS_CHUNK_1: [u8; 18] = [
0xB1, 0xCF, 0x28, 0x88, 0x00, 0x00, 0xF4, 0xC1, 0x18, 0x00, 0xF4, 0x41, 0x1B, 0x00, 0xF4, 0x01, 0x1F, 0x00,
];
pub const MAX_DATA_MESSAGE_SIZE: usize = 30;
pub struct DummySinkDevice {}
impl SinkDevicePolicyManager for DummySinkDevice {}
#[derive(Default)]
pub struct DummySinkEprDevice {
requested_epr_caps: bool,
}
impl DummySinkEprDevice {
pub fn new() -> Self {
Self::default()
}
}
impl SinkDevicePolicyManager for DummySinkEprDevice {
async fn get_event(
&mut self,
source_capabilities: &crate::protocol_layer::message::data::source_capabilities::SourceCapabilities,
) -> crate::sink::device_policy_manager::Event {
use crate::sink::device_policy_manager::Event;
if !self.requested_epr_caps {
if let Some(PowerDataObject::FixedSupply(fixed)) = source_capabilities.pdos().first() {
if fixed.epr_mode_capable() {
self.requested_epr_caps = true;
return Event::EnterEprMode(Power::new::<watt>(140)); }
}
}
Event::None
}
async fn request(
&mut self,
source_capabilities: &crate::protocol_layer::message::data::source_capabilities::SourceCapabilities,
) -> crate::protocol_layer::message::data::request::PowerSource {
use crate::protocol_layer::message::data::request::{CurrentRequest, PowerSource, VoltageRequest};
use crate::protocol_layer::message::data::source_capabilities::PowerDataObject;
let first_epr_pdo = source_capabilities
.epr_pdos()
.filter(|(_, pdo)| !pdo.is_zero_padding())
.find(|(_, pdo)| matches!(pdo, PowerDataObject::FixedSupply(_)));
if let Some((position, pdo)) = first_epr_pdo {
use crate::protocol_layer::message::data::request::FixedVariableSupply;
let mut rdo = FixedVariableSupply(0)
.with_object_position(position)
.with_usb_communications_capable(true)
.with_no_usb_suspend(true);
if let PowerDataObject::FixedSupply(fixed) = pdo {
let max_current = fixed.raw_max_current();
rdo = rdo
.with_raw_operating_current(max_current)
.with_raw_max_operating_current(max_current);
}
PowerSource::EprRequest(EprRequestDataObject { rdo: rdo.0, pdo: *pdo })
} else {
PowerSource::new_fixed(CurrentRequest::Highest, VoltageRequest::Safe5V, source_capabilities).unwrap()
}
}
}
pub struct DummyTimer {}
impl Timer for DummyTimer {
async fn after_millis(_milliseconds: u64) {
pending().await
}
}
pub struct DummyDriver<const N: usize> {
rx_vec: Vec<heapless::Vec<u8, N>>,
tx_vec: Vec<heapless::Vec<u8, N>>,
}
impl<const N: usize> Default for DummyDriver<N> {
fn default() -> Self {
Self {
rx_vec: Vec::new(),
tx_vec: Vec::new(),
}
}
}
impl<const N: usize> DummyDriver<N> {
pub fn new() -> Self {
Self::default()
}
pub fn inject_received_data(&mut self, data: &[u8]) {
let mut vec = heapless::Vec::new();
vec.extend_from_slice(data).unwrap();
self.rx_vec.push(vec);
}
pub fn probe_transmitted_data(&mut self) -> heapless::Vec<u8, N> {
eprintln!("probe_transmitted_data called, tx_vec len: {}", self.tx_vec.len());
self.tx_vec.remove(0)
}
pub fn has_transmitted_data(&self) -> bool {
!self.tx_vec.is_empty()
}
}
impl<const N: usize> Driver for DummyDriver<N> {
async fn receive(&mut self, buffer: &mut [u8]) -> Result<usize, usbpd_traits::DriverRxError> {
if self.rx_vec.is_empty() {
pending().await
}
let first = self.rx_vec.remove(0);
let len = first.len();
buffer[..len].copy_from_slice(&first);
Ok(len)
}
async fn transmit(&mut self, data: &[u8]) -> Result<(), usbpd_traits::DriverTxError> {
let mut vec = heapless::Vec::new();
vec.extend_from_slice(data).unwrap();
self.tx_vec.push(vec);
Ok(())
}
async fn transmit_hard_reset(&mut self) -> Result<(), usbpd_traits::DriverTxError> {
Ok(())
}
async fn wait_for_vbus(&mut self) {
}
}
pub const DUMMY_CAPABILITIES: [u8; 30] = [
0xA1, 0x71, 0x2c, 0x91, 0x01, 0x08, 0x2c, 0xD1, 0x02, 0x00, 0x2C, 0xB1, 0x04, 0x00, 0xE1, 0x40, 0x06, 0x00, 0x64, 0x21, 0xDC, 0xC8, 0x3C, 0x21, 0x40, 0xC9, 0x2D, 0x21, 0xA4, 0xC9, ];
pub fn get_dummy_source_capabilities() -> Vec<PowerDataObject> {
vec![
PowerDataObject::FixedSupply(
FixedSupply::default()
.with_raw_voltage(100)
.with_raw_max_current(300)
.with_unconstrained_power(true),
),
PowerDataObject::FixedSupply(FixedSupply::default().with_raw_voltage(180).with_raw_max_current(300)),
PowerDataObject::FixedSupply(FixedSupply::default().with_raw_voltage(300).with_raw_max_current(300)),
PowerDataObject::FixedSupply(FixedSupply::default().with_raw_voltage(400).with_raw_max_current(225)),
PowerDataObject::Augmented(Augmented::Spr(
SprProgrammablePowerSupply::default()
.with_raw_max_current(100)
.with_raw_min_voltage(33)
.with_raw_max_voltage(110)
.with_pps_power_limited(true),
)),
PowerDataObject::Augmented(Augmented::Spr(
SprProgrammablePowerSupply::default()
.with_raw_max_current(60)
.with_raw_min_voltage(33)
.with_raw_max_voltage(160)
.with_pps_power_limited(true),
)),
PowerDataObject::Augmented(Augmented::Spr(
SprProgrammablePowerSupply::default()
.with_raw_max_current(45)
.with_raw_min_voltage(33)
.with_raw_max_voltage(210)
.with_pps_power_limited(true),
)),
]
}
#[cfg(test)]
mod tests {
use usbpd_traits::Driver;
use crate::dummy::{DummyDriver, MAX_DATA_MESSAGE_SIZE};
#[tokio::test]
async fn test_receive() {
let mut driver: DummyDriver<MAX_DATA_MESSAGE_SIZE> = DummyDriver::new();
let mut injected_data = [0u8; MAX_DATA_MESSAGE_SIZE];
injected_data[0] = 123;
driver.inject_received_data(&injected_data);
injected_data[1] = 255;
driver.inject_received_data(&injected_data);
let mut buf = [0u8; MAX_DATA_MESSAGE_SIZE];
driver.receive(&mut buf).await.unwrap();
assert_eq!(buf[0], 123);
assert_eq!(buf[1], 0);
let mut buf = [0u8; 30];
driver.receive(&mut buf).await.unwrap();
assert_eq!(buf[0], 123);
assert_eq!(buf[1], 255);
}
}