1use core::convert::TryFrom;
5
6use byteorder::{ByteOrder, LittleEndian};
7use proc_bitfield::bitfield;
8
9use crate::counters::Counter;
10use crate::protocol_layer::message::ParseError;
11use crate::{DataRole, PowerRole};
12
13bitfield! {
14 #[derive(Clone, Copy, PartialEq, Eq)]
15 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
16 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
17 pub struct Header(pub u16): Debug, FromStorage, IntoStorage {
19 pub extended: bool @ 15,
22 pub num_objects: u8 [get usize] @ 12..=14,
24 pub message_id: u8 @ 9..=11,
26 pub port_power_role: bool [get PowerRole, set PowerRole] @ 8,
28 pub spec_revision: u8 [try_get SpecificationRevision, set SpecificationRevision] @ 6..=7,
35 pub port_data_role: bool [get DataRole, set DataRole] @ 5,
37 pub message_type_raw: u8 @ 0..=4,
39 }
40}
41
42impl Header {
43 pub fn new_template(
45 port_data_role: DataRole,
46 port_power_role: PowerRole,
47 spec_revision: SpecificationRevision,
48 ) -> Self {
49 Self(0)
50 .with_port_data_role(port_data_role)
51 .with_port_power_role(port_power_role)
52 .with_spec_revision(spec_revision)
53 }
54
55 pub fn new(
57 template: Self,
58 message_id: Counter,
59 message_type: MessageType,
60 num_objects: u8,
61 extended: bool,
62 ) -> Self {
63 template
64 .with_message_id(message_id.value())
65 .with_message_type_raw(match message_type {
66 MessageType::Control(x) => x as u8,
67 MessageType::Extended(x) => x as u8,
68 MessageType::Data(x) => x as u8,
69 })
70 .with_num_objects(num_objects)
71 .with_extended(extended)
72 }
73
74 pub fn new_control(template: Self, message_id: Counter, message_type: ControlMessageType) -> Self {
76 Self::new(template, message_id, MessageType::Control(message_type), 0, false)
77 }
78
79 pub fn new_data(template: Self, message_id: Counter, message_type: DataMessageType, num_objects: u8) -> Self {
81 Self::new(
82 template,
83 message_id,
84 MessageType::Data(message_type),
85 num_objects,
86 false,
87 )
88 }
89
90 pub fn new_extended(
92 template: Self,
93 message_id: Counter,
94 extended_message_type: ExtendedMessageType,
95 num_objects: u8,
96 ) -> Self {
97 Self::new(
98 template,
99 message_id,
100 MessageType::Extended(extended_message_type),
101 num_objects,
102 true,
103 )
104 }
105
106 pub fn from_bytes(buf: &[u8]) -> Result<Self, ParseError> {
108 assert!(buf.len() == 2);
109
110 let header = Header(LittleEndian::read_u16(buf));
111 header.spec_revision()?;
113 Ok(header)
114 }
115
116 pub fn to_bytes(self, buf: &mut [u8]) -> usize {
118 LittleEndian::write_u16(buf, self.0);
119 2
120 }
121
122 pub fn message_type(&self) -> MessageType {
124 if self.extended() {
126 MessageType::Extended(self.message_type_raw().into())
127 } else if self.num_objects() == 0 {
128 MessageType::Control(self.message_type_raw().into())
129 } else {
130 MessageType::Data(self.message_type_raw().into())
131 }
132 }
133}
134
135#[derive(Debug, Clone, Copy)]
137#[cfg_attr(feature = "defmt", derive(defmt::Format))]
138#[allow(non_camel_case_types)]
139pub enum SpecificationRevision {
140 R1_0,
142 R2_0,
144 R3_X,
146}
147
148impl TryFrom<u8> for SpecificationRevision {
149 type Error = ParseError;
150 fn try_from(value: u8) -> Result<Self, Self::Error> {
151 match value {
152 0b00 => Ok(Self::R1_0),
153 0b01 => Ok(Self::R2_0),
154 0b10 => Ok(Self::R3_X),
155 _ => Err(ParseError::UnsupportedSpecificationRevision(value)),
156 }
157 }
158}
159
160impl From<SpecificationRevision> for u8 {
161 fn from(value: SpecificationRevision) -> Self {
162 match value {
163 SpecificationRevision::R1_0 => 0b00,
164 SpecificationRevision::R2_0 => 0b01,
165 SpecificationRevision::R3_X => 0b10,
166 }
167 }
168}
169
170#[derive(Clone, Copy, Debug, PartialEq, Eq)]
172#[cfg_attr(feature = "defmt", derive(defmt::Format))]
173pub enum MessageType {
174 Control(ControlMessageType),
176 Data(DataMessageType),
178 Extended(ExtendedMessageType),
180}
181
182#[allow(missing_docs)]
184#[derive(Clone, Copy, Debug, PartialEq, Eq)]
185#[cfg_attr(feature = "defmt", derive(defmt::Format))]
186pub enum ControlMessageType {
187 GoodCRC = 0b0_0001,
188 GotoMin = 0b0_0010,
189 Accept = 0b0_0011,
190 Reject = 0b0_0100,
191 Ping = 0b0_0101,
192 PsRdy = 0b0_0110,
193 GetSourceCap = 0b0_0111,
194 GetSinkCap = 0b0_1000,
195 DrSwap = 0b0_1001,
196 PrSwap = 0b0_1010,
197 VconnSwap = 0b0_1011,
198 Wait = 0b0_1100,
199 SoftReset = 0b0_1101,
200 DataReset = 0b0_1110,
201 DataResetComplete = 0b0_1111,
202 NotSupported = 0b1_0000,
203 GetSourceCapExtended = 0b1_0001,
204 GetStatus = 0b1_0010,
205 FrSwap = 0b1_0011,
206 GetPpsStatus = 0b1_0100,
207 GetCountryCodes = 0b1_0101,
208 GetSinkCapExtended = 0b1_0110,
209 GetSourceInfo = 0b1_0111,
210 GetRevision = 0b1_1000,
211 Reserved,
212}
213
214impl From<u8> for ControlMessageType {
215 fn from(value: u8) -> Self {
216 match value {
217 0b0_0001 => Self::GoodCRC,
218 0b0_0010 => Self::GotoMin,
219 0b0_0011 => Self::Accept,
220 0b0_0100 => Self::Reject,
221 0b0_0101 => Self::Ping,
222 0b0_0110 => Self::PsRdy,
223 0b0_0111 => Self::GetSourceCap,
224 0b0_1000 => Self::GetSinkCap,
225 0b0_1001 => Self::DrSwap,
226 0b0_1010 => Self::PrSwap,
227 0b0_1011 => Self::VconnSwap,
228 0b0_1100 => Self::Wait,
229 0b0_1101 => Self::SoftReset,
230 0b0_1110 => Self::DataReset,
231 0b0_1111 => Self::DataResetComplete,
232 0b1_0000 => Self::NotSupported,
233 0b1_0001 => Self::GetSourceCapExtended,
234 0b1_0010 => Self::GetStatus,
235 0b1_0011 => Self::FrSwap,
236 0b1_0100 => Self::GetPpsStatus,
237 0b1_0101 => Self::GetCountryCodes,
238 0b1_0110 => Self::GetSinkCapExtended,
239 0b1_0111 => Self::GetSourceInfo,
240 0b1_1000 => Self::GetRevision,
241 _ => Self::Reserved,
242 }
243 }
244}
245
246#[derive(Clone, Copy, Debug, PartialEq, Eq)]
248#[cfg_attr(feature = "defmt", derive(defmt::Format))]
249#[allow(missing_docs)]
250pub enum DataMessageType {
251 SourceCapabilities = 0b0_0001,
252 Request = 0b0_0010,
253 Bist = 0b0_0011,
254 SinkCapabilities = 0b0_0100,
255 BatteryStatus = 0b0_0101,
256 Alert = 0b0_0110,
257 GetCountryInfo = 0b0_0111,
258 EnterUsb = 0b0_1000,
259 EprRequest = 0b0_1001,
260 EprMode = 0b0_1010,
261 SourceInfo = 0b0_1011,
262 Revision = 0b0_1100,
263 VendorDefined = 0b0_1111,
264 Reserved,
265}
266
267impl From<u8> for DataMessageType {
268 fn from(value: u8) -> Self {
269 match value {
270 0b0_0001 => Self::SourceCapabilities,
271 0b0_0010 => Self::Request,
272 0b0_0011 => Self::Bist,
273 0b0_0100 => Self::SinkCapabilities,
274 0b0_0101 => Self::BatteryStatus,
275 0b0_0110 => Self::Alert,
276 0b0_0111 => Self::GetCountryInfo,
277 0b0_1000 => Self::EnterUsb,
278 0b0_1001 => Self::EprRequest,
279 0b0_1010 => Self::EprMode,
280 0b0_1011 => Self::SourceInfo,
281 0b0_1100 => Self::Revision,
282 0b0_1111 => Self::VendorDefined,
283 _ => Self::Reserved,
284 }
285 }
286}
287
288impl From<u8> for ExtendedMessageType {
289 fn from(value: u8) -> Self {
290 match value {
291 0b0_0001 => Self::SourceCapabilitiesExtended,
292 0b0_0010 => Self::Status,
293 0b0_0011 => Self::GetBatteryCap,
294 0b0_0100 => Self::GetBatteryStatus,
295 0b0_0101 => Self::BatteryCapabilities,
296 0b0_0110 => Self::GetManufacturerInfo,
297 0b0_0111 => Self::ManufacturerInfo,
298 0b0_1000 => Self::SecurityRequest,
299 0b0_1001 => Self::SecurityResponse,
300 0b0_1010 => Self::FirmwareUpdateRequest,
301 0b0_1011 => Self::FirmwareUpdateResponse,
302 0b0_1100 => Self::PpsStatus,
303 0b0_1101 => Self::CountryInfo,
304 0b0_1110 => Self::CountryCodes,
305 0b0_1111 => Self::SinkCapabilitiesExtended,
306 0b1_0000 => Self::ExtendedControl,
307 0b1_0001 => Self::EprSourceCapabilities,
308 0b1_0010 => Self::EprSinkCapabilities,
309 0b1_1110 => Self::VendorDefinedExtended,
310 _ => Self::Reserved,
311 }
312 }
313}
314
315#[derive(Clone, Copy, Debug, PartialEq, Eq)]
317#[cfg_attr(feature = "defmt", derive(defmt::Format))]
318#[allow(missing_docs)]
319pub enum ExtendedMessageType {
320 SourceCapabilitiesExtended = 0b0_0001,
321 Status = 0b0_0010,
322 GetBatteryCap = 0b0_0011,
323 GetBatteryStatus = 0b0_0100,
324 BatteryCapabilities = 0b0_0101,
325 GetManufacturerInfo = 0b0_0110,
326 ManufacturerInfo = 0b0_0111,
327 SecurityRequest = 0b0_1000,
328 SecurityResponse = 0b0_1001,
329 FirmwareUpdateRequest = 0b0_1010,
330 FirmwareUpdateResponse = 0b0_1011,
331 PpsStatus = 0b0_1100,
332 CountryInfo = 0b0_1101,
333 CountryCodes = 0b0_1110,
334 SinkCapabilitiesExtended = 0b0_1111,
335 ExtendedControl = 0b1_0000,
336 EprSourceCapabilities = 0b1_0001,
337 EprSinkCapabilities = 0b1_0010,
338 VendorDefinedExtended = 0b1_1110,
339 Reserved,
340}