usb_pd/
message.rs

1use {
2    crate::{
3        header::{ControlMessageType, DataMessageType, Header, MessageType},
4        pdo::{
5            AugmentedPowerDataObject, AugmentedPowerDataObjectRaw, Battery,
6            EPRAdjustableVoltageSupply, FixedSupply, PowerDataObject, PowerDataObjectRaw,
7            SPRProgrammablePowerSupply, VariableSupply,
8        },
9    },
10    byteorder::{ByteOrder, LittleEndian},
11    defmt::{warn, Format},
12    heapless::Vec,
13};
14
15#[derive(Clone, Format)]
16pub enum Message {
17    Accept,
18    Reject,
19    Ready,
20    SourceCapabilities(Vec<PowerDataObject, 8>),
21    Unknown,
22}
23
24impl Message {
25    pub fn parse(header: Header, payload: &[u8]) -> Self {
26        match header.message_type() {
27            MessageType::Control(ControlMessageType::Accept) => Message::Accept,
28            MessageType::Control(ControlMessageType::Reject) => Message::Reject,
29            MessageType::Control(ControlMessageType::PsRdy) => Message::Ready,
30            MessageType::Data(DataMessageType::SourceCapabilities) => Message::SourceCapabilities(
31                payload
32                    .chunks_exact(4)
33                    .take(header.num_objects())
34                    .map(|buf| PowerDataObjectRaw(LittleEndian::read_u32(buf)))
35                    .map(|pdo| match pdo.kind() {
36                        0b00 => PowerDataObject::FixedSupply(FixedSupply(pdo.0)),
37                        0b01 => PowerDataObject::Battery(Battery(pdo.0)),
38                        0b10 => PowerDataObject::VariableSupply(VariableSupply(pdo.0)),
39                        0b11 => PowerDataObject::AugmentedPowerDataObject({
40                            match AugmentedPowerDataObjectRaw(pdo.0).supply() {
41                                0b00 => {
42                                    AugmentedPowerDataObject::SPR(SPRProgrammablePowerSupply(pdo.0))
43                                }
44                                0b01 => {
45                                    AugmentedPowerDataObject::EPR(EPRAdjustableVoltageSupply(pdo.0))
46                                }
47                                _ => unreachable!(),
48                            }
49                        }),
50                        _ => unreachable!(),
51                    })
52                    .collect(),
53            ),
54            _ => {
55                warn!("unknown message type");
56                Message::Unknown
57            }
58        }
59    }
60}