use heterob::{bit_numbering::Lsb, endianness::Le, Seq, P2, P5, P7};
use super::ExtendedCapabilityDataError;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PowerBudgeting {
pub data_select: u8,
pub data: Data,
pub power_budget_capability: PowerBudgetCapability,
}
impl TryFrom<&[u8]> for PowerBudgeting {
type Error = ExtendedCapabilityDataError;
fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
let Seq {
head: Le((data_select, rsvdp_0, data, power_budget_capability, rsvdp_1)),
..
} = P5(slice)
.try_into()
.map_err(|_| ExtendedCapabilityDataError {
name: "Power Budgeting",
size: 12,
})?;
let _: ([u8; 3], [u8; 3]) = (rsvdp_0, rsvdp_1);
let Lsb((
base_power,
data_scale,
pm_sub_state,
pm_state,
operation_condition_type,
power_rail,
(),
)) = P7::<u32, 8, 2, 3, 2, 3, 3, 11>(data).into();
let Lsb((system_allocated, ())) = P2::<u8, 1, 7>(power_budget_capability).into();
Ok(Self {
data_select,
data: Data {
base_power: From::<u8>::from(base_power),
data_scale: From::<u8>::from(data_scale),
pm_sub_state: From::<u8>::from(pm_sub_state),
pm_state: From::<u8>::from(pm_state),
operation_condition_type: From::<u8>::from(operation_condition_type),
power_rail: From::<u8>::from(power_rail),
},
power_budget_capability: PowerBudgetCapability { system_allocated },
})
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Data {
pub base_power: BasePower,
pub data_scale: DataScale,
pub pm_sub_state: PmSubState,
pub pm_state: PmState,
pub operation_condition_type: OperationConditionType,
pub power_rail: PowerRail,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum BasePower {
Value(u8),
Gt239Le250,
Gt250Le275,
Gt275Le300,
Gt300,
}
impl From<u8> for BasePower {
fn from(byte: u8) -> Self {
match byte {
v @ 0x00..=0xEF => Self::Value(v),
0xF0 => Self::Gt239Le250,
0xF1 => Self::Gt250Le275,
0xF2 => Self::Gt275Le300,
_ => Self::Gt300,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DataScale {
One,
Deci,
Centi,
Milli,
}
impl DataScale {
pub fn multiplier(&self) -> f64 {
match self {
Self::One => 1.0,
Self::Deci => 0.1,
Self::Centi => 0.01,
Self::Milli => 0.001,
}
}
}
impl From<u8> for DataScale {
fn from(byte: u8) -> Self {
match byte {
0b00 => Self::One,
0b01 => Self::Deci,
0b10 => Self::Centi,
0b11 => Self::Milli,
_ => unreachable!(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PmSubState {
Default,
Specific(u8),
}
impl From<u8> for PmSubState {
fn from(byte: u8) -> Self {
match byte {
0b00 => Self::Default,
v => Self::Specific(v),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PmState {
D0,
D1,
D2,
D3,
}
impl From<u8> for PmState {
fn from(byte: u8) -> Self {
match byte {
0b00 => Self::D0,
0b01 => Self::D1,
0b10 => Self::D2,
0b11 => Self::D3,
_ => unreachable!(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum OperationConditionType {
PmeAux,
Auxiliary,
Idle,
Sustained,
SustainedEmergencyPowerReductionState,
MaximumEmergencyPowerReductionState,
Maximum,
Reserved(u8),
}
impl From<u8> for OperationConditionType {
fn from(byte: u8) -> Self {
match byte {
0b000 => Self::PmeAux,
0b001 => Self::Auxiliary,
0b010 => Self::Idle,
0b011 => Self::Sustained,
0b100 => Self::SustainedEmergencyPowerReductionState,
0b101 => Self::MaximumEmergencyPowerReductionState,
0b111 => Self::Maximum,
v => Self::Reserved(v),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PowerRail {
Power12v,
Power3_3v,
Power1_5vOr1_8v,
Thermal,
Reserved(u8),
}
impl From<u8> for PowerRail {
fn from(byte: u8) -> Self {
match byte {
0b00 => Self::Power12v,
0b01 => Self::Power3_3v,
0b10 => Self::Power1_5vOr1_8v,
0b11 => Self::Thermal,
v => Self::Reserved(v),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PowerBudgetCapability {
pub system_allocated: bool,
}