usb_pd/
header.rs

1use {
2    crate::{DataRole, PowerRole},
3    byteorder::{ByteOrder, LittleEndian},
4    defmt::Format,
5    proc_bitfield::bitfield,
6};
7
8bitfield! {
9    #[derive(Clone, Copy, PartialEq, Eq)]
10    pub struct Header(pub u16): FromRaw, IntoRaw {
11        pub extended: bool @ 15,
12        pub num_objects: u8 [get usize] @ 12..=14,
13        pub message_id: u8 @ 9..=11,
14        pub port_power_role: bool [get PowerRole, set PowerRole] @ 8,
15        pub spec_revision: u8 [get SpecificationRevision, set SpecificationRevision] @ 6..=7,
16        pub port_data_role: bool [get DataRole, set DataRole] @ 5,
17        pub message_type_raw: u8 @ 0..4,
18    }
19}
20
21impl Header {
22    pub fn from_bytes(buf: &[u8]) -> Self {
23        assert!(buf.len() == 2);
24
25        Header(LittleEndian::read_u16(buf))
26    }
27
28    pub fn to_bytes(&self, buf: &mut [u8]) {
29        LittleEndian::write_u16(buf, self.0);
30    }
31
32    pub fn message_type(&self) -> MessageType {
33        if self.num_objects() == 0 {
34            MessageType::Control(self.message_type_raw().into())
35        } else {
36            MessageType::Data(self.message_type_raw().into())
37        }
38    }
39}
40
41#[derive(Format)]
42pub enum SpecificationRevision {
43    R1_0,
44    R2_0,
45    R3_0,
46}
47
48impl From<u8> for SpecificationRevision {
49    fn from(value: u8) -> Self {
50        match value {
51            0b00 => Self::R1_0,
52            0b01 => Self::R2_0,
53            0b10 => Self::R3_0,
54            _ => unimplemented!(),
55        }
56    }
57}
58
59impl From<SpecificationRevision> for u8 {
60    fn from(value: SpecificationRevision) -> Self {
61        match value {
62            SpecificationRevision::R1_0 => 0b00,
63            SpecificationRevision::R2_0 => 0b01,
64            SpecificationRevision::R3_0 => 0b10,
65        }
66    }
67}
68
69#[derive(Clone, Copy, PartialEq, Eq)]
70pub enum MessageType {
71    Control(ControlMessageType),
72    Data(DataMessageType),
73}
74
75#[derive(Clone, Copy, PartialEq, Eq)]
76pub enum ControlMessageType {
77    GoodCRC = 0b0_0001,
78    GotoMin = 0b0_0010,
79    Accept = 0b0_0011,
80    Reject = 0b0_0100,
81    Ping = 0b0_0101,
82    PsRdy = 0b0_0110,
83    GetSourceCap = 0b0_0111,
84    GetSinkCap = 0b0_1000,
85    DrSwap = 0b0_1001,
86    PrSwap = 0b0_1010,
87    VconnSwap = 0b0_1011,
88    Wait = 0b0_1100,
89    SoftReset = 0b0_1101,
90    DataReset = 0b0_1110,
91    DataResetComplete = 0b0_1111,
92    NotSupported = 0b1_0000,
93    GetSourceCapExtended = 0b1_0001,
94    GetStatus = 0b1_0010,
95    FrSwap = 0b1_0011,
96    GetPpsStatus = 0b1_0100,
97    GetCountryCodes = 0b1_0101,
98    GetSinkCapExtended = 0b1_0110,
99    GetSourceInfo = 0b1_0111,
100    GetRevision = 0b1_1000,
101    Reserved,
102}
103
104impl From<u8> for ControlMessageType {
105    fn from(value: u8) -> Self {
106        match value {
107            0b0_0001 => Self::GoodCRC,
108            0b0_0010 => Self::GotoMin,
109            0b0_0011 => Self::Accept,
110            0b0_0100 => Self::Reject,
111            0b0_0101 => Self::Ping,
112            0b0_0110 => Self::PsRdy,
113            0b0_0111 => Self::GetSourceCap,
114            0b0_1000 => Self::GetSinkCap,
115            0b0_1001 => Self::DrSwap,
116            0b0_1010 => Self::PrSwap,
117            0b0_1011 => Self::VconnSwap,
118            0b0_1100 => Self::Wait,
119            0b0_1101 => Self::SoftReset,
120            0b0_1110 => Self::DataReset,
121            0b0_1111 => Self::DataResetComplete,
122            0b1_0000 => Self::NotSupported,
123            0b1_0001 => Self::GetSourceCapExtended,
124            0b1_0010 => Self::GetStatus,
125            0b1_0011 => Self::FrSwap,
126            0b1_0100 => Self::GetPpsStatus,
127            0b1_0101 => Self::GetCountryCodes,
128            0b1_0110 => Self::GetSinkCapExtended,
129            0b1_0111 => Self::GetSourceInfo,
130            0b1_1000 => Self::GetRevision,
131            _ => Self::Reserved,
132        }
133    }
134}
135
136#[derive(Clone, Copy, PartialEq, Eq)]
137pub enum DataMessageType {
138    SourceCapabilities = 0b0_0001,
139    Request = 0b0_0010,
140    Bist = 0b0_0011,
141    SinkCapabilities = 0b0_0100,
142    BatteryStatus = 0b0_0101,
143    Alert = 0b0_0110,
144    GetCountryInfo = 0b0_0111,
145    EnterUsb = 0b0_1000,
146    EprRequest = 0b0_1001,
147    EprMode = 0b0_1010,
148    SourceInfo = 0b0_1011,
149    Revision = 0b0_1100,
150    VendorDefined = 0b0_1111,
151    Reserved,
152}
153
154impl From<u8> for DataMessageType {
155    fn from(value: u8) -> Self {
156        match value {
157            0b0_0001 => Self::SourceCapabilities,
158            0b0_0010 => Self::Request,
159            0b0_0011 => Self::Bist,
160            0b0_0100 => Self::SinkCapabilities,
161            0b0_0101 => Self::BatteryStatus,
162            0b0_0110 => Self::Alert,
163            0b0_0111 => Self::GetCountryInfo,
164            0b0_1000 => Self::EnterUsb,
165            0b0_1001 => Self::EprRequest,
166            0b0_1010 => Self::EprMode,
167            0b0_1011 => Self::SourceInfo,
168            0b0_1100 => Self::Revision,
169            0b0_1111 => Self::VendorDefined,
170            _ => Self::Reserved,
171        }
172    }
173}