1use crate::adc::{AdcDataRaw, AdcDataSimple};
2use crate::adcqueue::{AdcQueueData, GraphSampleRate};
3use crate::auth::{self, HardwareId, StreamingAuthResult};
4use crate::constants::*;
5use crate::error::KMError;
6use crate::packet::{
7 Attribute, AttributeSet, CtrlHeader, DataHeader, LogicalPacket, PacketType, RawPacket, StreamingAuthHeader,
8};
9use crate::pd::{PdEventStream, PdStatus, PdStatusRaw};
10use bytes::Bytes;
11use num_enum::FromPrimitive;
12use uom::si::electric_current::milliampere;
13use uom::si::electric_potential::millivolt;
14use zerocopy::{FromBytes, IntoBytes};
15
16const PD_MONITOR_ENABLED_PARAMETER: u16 = 1;
17const PD_MONITOR_DISABLED_PARAMETER: u16 = 0;
18
19#[derive(Debug, Clone, PartialEq)]
21#[cfg_attr(feature = "python", derive(pyo3::IntoPyObject))]
22pub enum PayloadData {
23 Adc(AdcDataSimple),
24 AdcQueue(AdcQueueData),
25 PdStatus(PdStatus),
26 PdEvents(PdEventStream),
27 Unknown { attribute: Attribute, data: Vec<u8> },
28}
29
30#[derive(Debug, Clone, PartialEq)]
31pub enum Packet {
32 DataResponse { payloads: Vec<PayloadData> },
34 GetData { attribute_mask: u16 },
36 StartGraph { rate_index: u16 },
41 StopGraph,
43 Accept { id: u8 },
45 Reject { id: u8 },
47 NotReadable { id: u8 },
49 Connect,
51 Disconnect,
53 EnablePdMonitor,
55 DisablePdMonitor,
57 MemoryRead {
59 address: u32,
61 size: u32,
63 },
64 MemoryReadResponse {
66 data: Vec<u8>,
68 },
69 StreamingAuth {
71 hardware_id: HardwareId,
73 },
74 StreamingAuthResponse(StreamingAuthResult),
76 Generic(RawPacket),
78}
79
80impl Packet {
81 pub fn get_adc(&self) -> Option<&AdcDataSimple> {
83 match self {
84 Self::DataResponse { payloads } => payloads.iter().find_map(|p| match p {
85 PayloadData::Adc(adc) => Some(adc),
86 _ => None,
87 }),
88 _ => None,
89 }
90 }
91
92 pub fn get_adc_queue(&self) -> Option<&AdcQueueData> {
94 match self {
95 Self::DataResponse { payloads } => payloads.iter().find_map(|p| match p {
96 PayloadData::AdcQueue(queue) => Some(queue),
97 _ => None,
98 }),
99 _ => None,
100 }
101 }
102
103 pub fn get_pd_status(&self) -> Option<&PdStatus> {
105 match self {
106 Self::DataResponse { payloads } => payloads.iter().find_map(|p| match p {
107 PayloadData::PdStatus(pd) => Some(pd),
108 _ => None,
109 }),
110 _ => None,
111 }
112 }
113
114 pub fn get_pd_events(&self) -> Option<&PdEventStream> {
116 match self {
117 Self::DataResponse { payloads } => payloads.iter().find_map(|p| match p {
118 PayloadData::PdEvents(events) => Some(events),
119 _ => None,
120 }),
121 _ => None,
122 }
123 }
124
125 pub fn has_payload(&self, attr: Attribute) -> bool {
127 match self {
128 Self::DataResponse { payloads } => payloads.iter().any(|p| match p {
129 PayloadData::Adc(_) => attr == Attribute::Adc,
130 PayloadData::AdcQueue(_) => attr == Attribute::AdcQueue,
131 PayloadData::PdStatus(_) | PayloadData::PdEvents(_) => attr == Attribute::PdPacket,
132 PayloadData::Unknown { attribute, .. } => *attribute == attr,
133 }),
134 _ => false,
135 }
136 }
137}
138
139impl TryFrom<RawPacket> for Packet {
140 type Error = KMError;
141
142 fn try_from(raw_packet: RawPacket) -> Result<Self, Self::Error> {
143 Self::from_raw(raw_packet, None)
144 }
145}
146
147impl Packet {
148 pub fn from_raw_with_graph_rate(raw_packet: RawPacket, rate: GraphSampleRate) -> Result<Self, KMError> {
153 Self::from_raw(raw_packet, Some(rate))
154 }
155
156 fn from_raw(raw_packet: RawPacket, graph_rate: Option<GraphSampleRate>) -> Result<Self, KMError> {
157 match raw_packet {
158 RawPacket::Ctrl { header, payload } => {
159 let packet_type = PacketType::from_primitive(header.packet_type());
160 let attribute_set = AttributeSet::from_raw(header.attribute());
161
162 match packet_type {
163 PacketType::GetData => Ok(Packet::GetData {
164 attribute_mask: attribute_set.raw(),
165 }),
166 PacketType::StartGraph => Ok(Packet::StartGraph {
167 rate_index: attribute_set.raw(),
168 }),
169 PacketType::StopGraph => Ok(Packet::StopGraph),
170 PacketType::Accept => Ok(Packet::Accept { id: header.id() }),
171 PacketType::Rejected => Ok(Packet::Reject { id: header.id() }),
172 PacketType::NotReadable => Ok(Packet::NotReadable { id: header.id() }),
173 PacketType::Connect => Ok(Packet::Connect),
174 PacketType::Disconnect => Ok(Packet::Disconnect),
175 _ => Ok(Packet::Generic(RawPacket::Ctrl { header, payload })),
176 }
177 }
178 RawPacket::SimpleData { header, payload } => {
179 let packet_type = PacketType::from_primitive(header.packet_type());
180
181 match packet_type {
182 PacketType::MemoryRead => {
184 Ok(Packet::Accept { id: header.id() })
186 }
187 PacketType::StreamingAuth => {
189 let auth_header = StreamingAuthHeader::from_bytes(header.into_bytes());
190 if let Some(result) = auth::parse_streaming_auth_response_parts(auth_header, &payload) {
191 Ok(Packet::StreamingAuthResponse(result))
192 } else {
193 Ok(Packet::Generic(RawPacket::SimpleData { header, payload }))
194 }
195 }
196 _ => Ok(Packet::Generic(RawPacket::SimpleData { header, payload })),
197 }
198 }
199 RawPacket::Data { logical_packets, .. } => {
200 let mut payloads = Vec::new();
202
203 for lp in logical_packets {
204 let payload_data = match lp.attribute {
205 Attribute::Adc => {
206 if lp.payload.len() < ADC_DATA_SIZE {
208 return Err(KMError::InvalidPacket(format!(
209 "ADC payload too small: expected {}, got {}",
210 ADC_DATA_SIZE,
211 lp.payload.len()
212 )));
213 }
214
215 let adc_data_raw = AdcDataRaw::ref_from_bytes(&lp.payload[..ADC_DATA_SIZE])
216 .map_err(|_| KMError::InvalidPacket("Failed to parse ADC data".to_string()))?;
217 let adc_data = AdcDataSimple::from(*adc_data_raw);
218 PayloadData::Adc(adc_data)
219 }
220 Attribute::AdcQueue => {
221 let adcqueue = if let Some(rate) = graph_rate {
225 AdcQueueData::from_bytes_with_rate(lp.payload.as_ref(), rate)?
226 } else {
227 AdcQueueData::from_bytes(lp.payload.as_ref())?
228 };
229 PayloadData::AdcQueue(adcqueue)
230 }
231 Attribute::PdPacket => {
232 if lp.payload.len() == PD_STATUS_SIZE {
234 let pd_status_raw = PdStatusRaw::ref_from_bytes(lp.payload.as_ref())
236 .map_err(|_| KMError::InvalidPacket("Failed to parse PD status".to_string()))?;
237 PayloadData::PdStatus(PdStatus::from(*pd_status_raw))
238 } else {
239 let pd_events = PdEventStream::from_bytes(Bytes::from(lp.payload))?;
241 PayloadData::PdEvents(pd_events)
242 }
243 }
244 _ => PayloadData::Unknown {
245 attribute: lp.attribute,
246 data: lp.payload.to_vec(),
247 },
248 };
249
250 payloads.push(payload_data);
251 }
252
253 Ok(Packet::DataResponse { payloads })
254 }
255 }
256 }
257}
258
259impl Packet {
260 pub fn to_raw_packet(self, id: u8) -> Result<RawPacket, KMError> {
262 let raw_packet = match self {
263 Packet::DataResponse { payloads } => {
264 let mut logical_packets = Vec::new();
265
266 for payload in payloads {
267 match payload {
268 PayloadData::Adc(adc) => {
269 let adc_raw = AdcDataRaw::from(adc);
270 logical_packets.push(LogicalPacket {
271 attribute: Attribute::Adc,
272 next: false, chunk: 0,
274 size: ADC_DATA_SIZE as u16,
275 payload: adc_raw.as_bytes().to_vec(),
276 });
277 }
278 PayloadData::PdStatus(pd_status) => {
279 let timestamp_bytes = pd_status.timestamp_ticks.to_le_bytes();
281 let mut raw_bytes = Vec::with_capacity(12);
282 raw_bytes.push(pd_status.type_id);
283 raw_bytes.extend_from_slice(×tamp_bytes[..3]); raw_bytes.extend_from_slice(&(pd_status.vbus.get::<millivolt>() as u16).to_le_bytes());
285 raw_bytes.extend_from_slice(&(pd_status.ibus.get::<milliampere>() as i16).to_le_bytes());
286 raw_bytes.extend_from_slice(&(pd_status.cc1.get::<millivolt>() as u16).to_le_bytes());
287 raw_bytes.extend_from_slice(&(pd_status.cc2.get::<millivolt>() as u16).to_le_bytes());
288
289 logical_packets.push(LogicalPacket {
290 attribute: Attribute::PdPacket,
291 next: false, chunk: 0,
293 size: PD_STATUS_SIZE as u16,
294 payload: raw_bytes,
295 });
296 }
297 PayloadData::AdcQueue(_) => {
298 return Err(KMError::UnsupportedSerialization { packet: "AdcQueue" });
299 }
300 PayloadData::PdEvents(_) => {
301 return Err(KMError::UnsupportedSerialization {
302 packet: "PdEventStream",
303 });
304 }
305 PayloadData::Unknown { attribute, data } => {
306 logical_packets.push(LogicalPacket {
307 attribute,
308 next: false, chunk: 0,
310 size: data.len() as u16,
311 payload: data,
312 });
313 }
314 }
315 }
316
317 if let Some((last, rest)) = logical_packets.split_last_mut() {
319 for lp in rest {
320 lp.next = true;
321 }
322 last.next = false;
323 }
324
325 let total_size: usize = logical_packets.iter().map(|lp| 4 + lp.payload.len()).sum();
327
328 let header = DataHeader::new()
329 .with_packet_type(PacketType::PutData.into())
330 .with_reserved_flag(true)
331 .with_id(id)
332 .with_obj_count_words((total_size / 4) as u16);
333
334 RawPacket::Data {
335 header,
336 logical_packets,
337 }
338 }
339 Packet::GetData { attribute_mask } => RawPacket::Ctrl {
340 header: CtrlHeader::new()
341 .with_packet_type(PacketType::GetData.into())
342 .with_reserved_flag(false)
343 .with_id(id)
344 .with_attribute(attribute_mask),
345 payload: Vec::new(),
346 },
347 Packet::StartGraph { rate_index } => RawPacket::Ctrl {
348 header: CtrlHeader::new()
349 .with_packet_type(PacketType::StartGraph.into())
350 .with_reserved_flag(false)
351 .with_id(id)
352 .with_attribute(rate_index),
353 payload: Vec::new(),
354 },
355 Packet::StopGraph => RawPacket::Ctrl {
356 header: CtrlHeader::new()
357 .with_packet_type(PacketType::StopGraph.into())
358 .with_reserved_flag(false)
359 .with_id(id)
360 .with_attribute(0),
361 payload: Vec::new(),
362 },
363 Packet::Accept { id: accept_id } => RawPacket::Ctrl {
364 header: CtrlHeader::new()
365 .with_packet_type(PacketType::Accept.into())
366 .with_reserved_flag(false)
367 .with_id(accept_id)
368 .with_attribute(0),
369 payload: Vec::new(),
370 },
371 Packet::Reject { id: reject_id } => RawPacket::Ctrl {
372 header: CtrlHeader::new()
373 .with_packet_type(PacketType::Rejected.into())
374 .with_reserved_flag(false)
375 .with_id(reject_id)
376 .with_attribute(0),
377 payload: Vec::new(),
378 },
379 Packet::NotReadable { id: nr_id } => RawPacket::Ctrl {
380 header: CtrlHeader::new()
381 .with_packet_type(PacketType::NotReadable.into())
382 .with_reserved_flag(false)
383 .with_id(nr_id)
384 .with_attribute(0),
385 payload: Vec::new(),
386 },
387 Packet::Connect => RawPacket::Ctrl {
388 header: CtrlHeader::new()
389 .with_packet_type(PacketType::Connect.into())
390 .with_reserved_flag(false)
391 .with_id(id)
392 .with_attribute(0),
393 payload: Vec::new(),
394 },
395 Packet::Disconnect => RawPacket::Ctrl {
396 header: CtrlHeader::new()
397 .with_packet_type(PacketType::Disconnect.into())
398 .with_reserved_flag(false)
399 .with_id(id)
400 .with_attribute(0),
401 payload: Vec::new(),
402 },
403 Packet::EnablePdMonitor => RawPacket::Ctrl {
404 header: CtrlHeader::new()
405 .with_packet_type(PacketType::EnablePdMonitor.into())
406 .with_reserved_flag(false)
407 .with_id(id)
408 .with_attribute(PD_MONITOR_ENABLED_PARAMETER),
409 payload: Vec::new(),
410 },
411 Packet::DisablePdMonitor => RawPacket::Ctrl {
412 header: CtrlHeader::new()
413 .with_packet_type(PacketType::DisablePdMonitor.into())
414 .with_reserved_flag(false)
415 .with_id(id)
416 .with_attribute(PD_MONITOR_DISABLED_PARAMETER),
417 payload: Vec::new(),
418 },
419 Packet::MemoryRead { address, size } => {
420 let encrypted_payload = auth::build_memory_read_payload(address, size);
422 RawPacket::SimpleData {
423 header: DataHeader::new()
424 .with_packet_type(PacketType::MemoryRead.into())
425 .with_reserved_flag(false)
426 .with_id(id)
427 .with_obj_count_words(0x0101), payload: encrypted_payload.to_vec(),
429 }
430 }
431 Packet::MemoryReadResponse { .. } => {
432 return Err(KMError::UnsupportedSerialization {
433 packet: "MemoryReadResponse",
434 });
435 }
436 Packet::StreamingAuth { hardware_id } => {
437 let encrypted_payload = auth::build_streaming_auth_payload(&hardware_id);
439 RawPacket::SimpleData {
440 header: DataHeader::new()
441 .with_packet_type(PacketType::StreamingAuth.into())
442 .with_reserved_flag(false)
443 .with_id(id)
444 .with_obj_count_words(0x0200), payload: encrypted_payload.to_vec(),
446 }
447 }
448 Packet::StreamingAuthResponse(result) => {
449 let encrypted_payload = auth::encrypt_streaming_auth_response_payload(&result.decrypted_payload);
451 let auth_header = StreamingAuthHeader::new()
452 .with_packet_type(PacketType::StreamingAuth.into())
453 .with_reserved_flag(false)
454 .with_id(auth::STREAMING_AUTH_RESPONSE_ID)
455 .with_attribute(result.attribute);
456 RawPacket::Ctrl {
457 header: CtrlHeader::from_bytes(auth_header.into_bytes()),
458 payload: encrypted_payload.to_vec(),
459 }
460 }
461 Packet::Generic(raw_packet) => raw_packet,
462 };
463
464 Ok(raw_packet)
465 }
466}
467
468#[cfg(feature = "python")]
470impl<'py> pyo3::IntoPyObject<'py> for Packet {
471 type Target = pyo3::PyAny;
472 type Output = pyo3::Bound<'py, Self::Target>;
473 type Error = pyo3::PyErr;
474
475 fn into_pyobject(self, py: pyo3::Python<'py>) -> Result<Self::Output, Self::Error> {
476 use pyo3::types::{PyDict, PyDictMethods};
477
478 let dict = PyDict::new(py);
479 match self {
480 Packet::DataResponse { payloads } => {
481 let inner = PyDict::new(py);
482 inner.set_item("payloads", payloads.into_pyobject(py)?)?;
483 dict.set_item("DataResponse", inner)?;
484 }
485 Packet::GetData { attribute_mask } => {
486 let inner = PyDict::new(py);
487 inner.set_item("attribute_mask", attribute_mask)?;
488 dict.set_item("GetData", inner)?;
489 }
490 Packet::StartGraph { rate_index } => {
491 let inner = PyDict::new(py);
492 inner.set_item("rate_index", rate_index)?;
493 dict.set_item("StartGraph", inner)?;
494 }
495 Packet::StopGraph => {
496 dict.set_item("StopGraph", py.None())?;
497 }
498 Packet::Accept { id } => {
499 let inner = PyDict::new(py);
500 inner.set_item("id", id)?;
501 dict.set_item("Accept", inner)?;
502 }
503 Packet::Reject { id } => {
504 let inner = PyDict::new(py);
505 inner.set_item("id", id)?;
506 dict.set_item("Reject", inner)?;
507 }
508 Packet::NotReadable { id } => {
509 let inner = PyDict::new(py);
510 inner.set_item("id", id)?;
511 dict.set_item("NotReadable", inner)?;
512 }
513 Packet::Connect => {
514 dict.set_item("Connect", py.None())?;
515 }
516 Packet::Disconnect => {
517 dict.set_item("Disconnect", py.None())?;
518 }
519 Packet::EnablePdMonitor => {
520 dict.set_item("EnablePdMonitor", py.None())?;
521 }
522 Packet::DisablePdMonitor => {
523 dict.set_item("DisablePdMonitor", py.None())?;
524 }
525 Packet::MemoryRead { address, size } => {
526 let inner = PyDict::new(py);
527 inner.set_item("address", address)?;
528 inner.set_item("size", size)?;
529 dict.set_item("MemoryRead", inner)?;
530 }
531 Packet::MemoryReadResponse { data } => {
532 let inner = PyDict::new(py);
533 inner.set_item("data", data)?;
534 dict.set_item("MemoryReadResponse", inner)?;
535 }
536 Packet::StreamingAuth { hardware_id } => {
537 let inner = PyDict::new(py);
538 inner.set_item("hardware_id", hex::encode(hardware_id.bytes))?;
539 dict.set_item("StreamingAuth", inner)?;
540 }
541 Packet::StreamingAuthResponse(result) => {
542 let inner = PyDict::new(py);
543 inner.set_item("success", result.success)?;
544 inner.set_item("auth_level", result.auth_level)?;
545 inner.set_item("attribute", result.attribute)?;
546 dict.set_item("StreamingAuthResponse", inner)?;
547 }
548 Packet::Generic(raw_packet) => {
549 dict.set_item("Generic", raw_packet.into_pyobject(py)?)?;
550 }
551 }
552 Ok(dict.into_any())
553 }
554}