1use std::{io::Cursor, time};
6
7use cameleon_impl::bytes_io::ReadBytes;
8
9use crate::u3v::{Error, Result};
10
11#[derive(Clone, Debug, PartialEq, Eq)]
12pub struct AckPacket<'a> {
13 ccd: AckCcd,
14 raw_scd: &'a [u8],
15}
16
17impl<'a> AckPacket<'a> {
18 const PREFIX_MAGIC: u32 = 0x4356_3355;
19
20 pub fn parse(buf: &'a (impl AsRef<[u8]> + ?Sized)) -> Result<Self> {
21 let mut cursor = Cursor::new(buf.as_ref());
22
23 Self::parse_prefix(&mut cursor)?;
24
25 let ccd = AckCcd::parse(&mut cursor)?;
26
27 let raw_scd = &cursor.get_ref()[cursor.position() as usize..];
28 Ok(Self { ccd, raw_scd })
29 }
30
31 #[must_use]
32 pub fn scd_kind(&self) -> ScdKind {
33 self.ccd.scd_kind
34 }
35
36 #[must_use]
37 pub fn ccd(&self) -> &AckCcd {
38 &self.ccd
39 }
40
41 #[must_use]
42 pub fn raw_scd(&self) -> &'a [u8] {
43 self.raw_scd
44 }
45
46 pub fn scd_as<T: ParseScd<'a>>(&self) -> Result<T> {
47 T::parse(self.raw_scd, &self.ccd)
48 }
49
50 #[must_use]
51 pub fn status(&self) -> &Status {
52 &self.ccd.status
53 }
54
55 #[must_use]
56 pub fn request_id(&self) -> u16 {
57 self.ccd.request_id
58 }
59
60 fn parse_prefix(cursor: &mut Cursor<&[u8]>) -> Result<()> {
61 let magic: u32 = cursor.read_bytes_le()?;
62 if magic == Self::PREFIX_MAGIC {
63 Ok(())
64 } else {
65 Err(Error::InvalidPacket("invalid prefix magic".into()))
66 }
67 }
68}
69
70#[derive(Clone, Debug, PartialEq, Eq)]
71pub struct AckCcd {
72 pub(crate) status: Status,
73 pub(crate) scd_kind: ScdKind,
74 pub(crate) request_id: u16,
75 pub(crate) scd_len: u16,
76}
77
78impl AckCcd {
79 #[must_use]
80 pub fn status(&self) -> Status {
81 self.status
82 }
83
84 #[must_use]
85 pub fn scd_kind(&self) -> ScdKind {
86 self.scd_kind
87 }
88
89 #[must_use]
90 pub fn request_id(&self) -> u16 {
91 self.request_id
92 }
93
94 #[must_use]
95 pub fn scd_len(&self) -> u16 {
96 self.scd_len
97 }
98
99 fn parse(cursor: &mut Cursor<&[u8]>) -> Result<Self> {
100 let status = Status::parse(cursor)?;
101 let scd_kind = ScdKind::parse(cursor)?;
102 let scd_len = cursor.read_bytes_le()?;
103 let request_id = cursor.read_bytes_le()?;
104
105 Ok(Self {
106 status,
107 scd_kind,
108 request_id,
109 scd_len,
110 })
111 }
112}
113
114#[derive(Clone, Copy, Debug, PartialEq, Eq)]
115pub struct Status {
116 pub(crate) code: u16,
117 pub(crate) kind: StatusKind,
118}
119
120#[derive(Clone, Copy, Debug, PartialEq, Eq)]
121pub enum StatusKind {
122 GenCp(GenCpStatus),
123 UsbSpecific(UsbSpecificStatus),
124 DeviceSpecific,
125}
126
127#[derive(Clone, Copy, Debug, PartialEq, Eq)]
128pub enum GenCpStatus {
129 Success,
131
132 NotImplemented,
134
135 InvalidParameter,
137
138 InvalidAddress,
140
141 WriteProtect,
143
144 BadAlignment,
146
147 AccessDenied,
149
150 Busy,
152
153 Timeout,
155
156 InvalidHeader,
158
159 WrongConfig,
161
162 GenericError,
164}
165
166#[derive(Clone, Copy, Debug, PartialEq, Eq)]
167pub enum UsbSpecificStatus {
168 ResendNotSupported,
170
171 StreamEndpointHalted,
173
174 PayloadSizeNotAligned,
176
177 EventEndpointHalted,
179
180 InvalidSiState,
183}
184
185impl Status {
186 #[must_use]
187 pub fn is_success(self) -> bool {
188 matches!(self.kind, StatusKind::GenCp(GenCpStatus::Success))
189 }
190
191 #[must_use]
192 pub fn is_fatal(self) -> bool {
193 self.code >> 15_i32 == 1
194 }
195
196 #[must_use]
197 pub fn code(self) -> u16 {
198 self.code
199 }
200
201 #[must_use]
202 pub fn kind(self) -> StatusKind {
203 self.kind
204 }
205
206 fn parse(cursor: &mut Cursor<&[u8]>) -> Result<Self> {
207 let code: u16 = cursor.read_bytes_le()?;
208
209 let namespace = (code >> 13_i32) & 0x11;
210 match namespace {
211 0b00 => Self::parse_gencp_status(code),
212 0b01 => Self::parse_usb_status(code),
213 0b10 => Ok(Self {
214 code,
215 kind: StatusKind::DeviceSpecific,
216 }),
217 _ => Err(Error::InvalidPacket(
218 "invalid ack status code, namespace is set to 0b11".into(),
219 )),
220 }
221 }
222
223 fn parse_gencp_status(code: u16) -> Result<Self> {
224 use GenCpStatus::{
225 AccessDenied, BadAlignment, Busy, GenericError, InvalidAddress, InvalidHeader,
226 InvalidParameter, NotImplemented, Success, Timeout, WriteProtect, WrongConfig,
227 };
228
229 debug_assert!((code >> 13).trailing_zeros() >= 2);
230
231 let status = match code {
232 0x0000 => Success,
233 0x8001 => NotImplemented,
234 0x8002 => InvalidParameter,
235 0x8003 => InvalidAddress,
236 0x8004 => WriteProtect,
237 0x8005 => BadAlignment,
238 0x8006 => AccessDenied,
239 0x8007 => Busy,
240 0x800B => Timeout,
241 0x800E => InvalidHeader,
242 0x800F => WrongConfig,
243 0x8FFF => GenericError,
244 _ => {
245 return Err(Error::InvalidPacket(
246 format! {"invalid gencp status code {:#X}", code}.into(),
247 ))
248 }
249 };
250
251 Ok(Self {
252 code,
253 kind: StatusKind::GenCp(status),
254 })
255 }
256
257 fn parse_usb_status(code: u16) -> Result<Self> {
258 use UsbSpecificStatus::{
259 EventEndpointHalted, InvalidSiState, PayloadSizeNotAligned, ResendNotSupported,
260 StreamEndpointHalted,
261 };
262
263 debug_assert!(code >> 13_i32 & 0b11 == 0b01);
264
265 let status = match code {
266 0xA001 => ResendNotSupported,
267 0xA002 => StreamEndpointHalted,
268 0xA003 => PayloadSizeNotAligned,
269 0xA004 => InvalidSiState,
270 0xA005 => EventEndpointHalted,
271 _ => {
272 return Err(Error::InvalidPacket(
273 format! {"invalid usb status code {:#X}", code}.into(),
274 ))
275 }
276 };
277
278 Ok(Self {
279 code,
280 kind: StatusKind::UsbSpecific(status),
281 })
282 }
283}
284
285#[derive(Clone, Copy, Debug, PartialEq, Eq)]
286pub enum ScdKind {
287 ReadMem,
288 WriteMem,
289 ReadMemStacked,
290 WriteMemStacked,
291 Pending,
292}
293
294impl ScdKind {
295 fn parse(cursor: &mut Cursor<&[u8]>) -> Result<Self> {
296 let id: u16 = cursor.read_bytes_le()?;
297 match id {
298 0x0801 => Ok(ScdKind::ReadMem),
299 0x0803 => Ok(ScdKind::WriteMem),
300 0x0805 => Ok(ScdKind::Pending),
301 0x0807 => Ok(ScdKind::ReadMemStacked),
302 0x0809 => Ok(ScdKind::WriteMemStacked),
303 _ => Err(Error::InvalidPacket(
304 format!("unknown ack command id {:#X}", id).into(),
305 )),
306 }
307 }
308}
309
310pub trait ParseScd<'a>: Sized {
311 fn parse(buf: &'a [u8], ccd: &AckCcd) -> Result<Self>;
312}
313
314pub struct ReadMem<'a> {
315 pub data: &'a [u8],
316}
317
318pub struct WriteMem {
319 pub length: u16,
320}
321
322pub struct Pending {
323 pub timeout: time::Duration,
324}
325
326pub struct ReadMemStacked<'a> {
327 pub data: &'a [u8],
328}
329
330pub struct WriteMemStacked {
331 pub lengths: Vec<u16>,
332}
333
334pub struct CustomAck<'a> {
335 pub data: &'a [u8],
336}
337
338impl<'a> ParseScd<'a> for ReadMem<'a> {
339 fn parse(buf: &'a [u8], ccd: &AckCcd) -> Result<Self> {
340 let scd_len = ccd.scd_len() as usize;
341 if buf.len() < scd_len {
342 return Err(Error::InvalidPacket(
343 "SCD length is smaller than specified length in CCD".into(),
344 ));
345 }
346 let data = &buf[..scd_len];
347 Ok(Self { data })
348 }
349}
350
351impl<'a> ParseScd<'a> for WriteMem {
352 fn parse(buf: &'a [u8], _ccd: &AckCcd) -> Result<Self> {
353 let mut cursor = Cursor::new(buf);
354 let reserved: u16 = cursor.read_bytes_le()?;
355 if reserved != 0 {
356 return Err(Error::InvalidPacket(
357 "the first two bytes of WriteMemAck scd must be set to zero".into(),
358 ));
359 }
360
361 let length = cursor.read_bytes_le()?;
362 Ok(Self { length })
363 }
364}
365
366impl<'a> ParseScd<'a> for Pending {
367 fn parse(buf: &'a [u8], _ccd: &AckCcd) -> Result<Self> {
368 let mut cursor = Cursor::new(buf);
369 let reserved: u16 = cursor.read_bytes_le()?;
370 if reserved != 0 {
371 return Err(Error::InvalidPacket(
372 "the first two bytes of PendingAck scd must be set to zero".into(),
373 ));
374 }
375
376 let timeout_ms: u16 = cursor.read_bytes_le()?;
377 let timeout = time::Duration::from_millis(timeout_ms.into());
378 Ok(Self { timeout })
379 }
380}
381
382impl<'a> ParseScd<'a> for ReadMemStacked<'a> {
383 fn parse(buf: &'a [u8], ccd: &AckCcd) -> Result<Self> {
384 let scd_len = ccd.scd_len() as usize;
385 if buf.len() < scd_len {
386 return Err(Error::InvalidPacket(
387 "SCD length is smaller than specified length in CCD".into(),
388 ));
389 }
390 let data = &buf[..scd_len];
391 Ok(Self { data })
392 }
393}
394
395impl<'a> ParseScd<'a> for WriteMemStacked {
396 fn parse(buf: &'a [u8], ccd: &AckCcd) -> Result<Self> {
397 let mut cursor = Cursor::new(buf);
398 let mut to_read = ccd.scd_len as usize;
399 let mut lengths = Vec::with_capacity(to_read / 4);
400
401 while to_read > 0 {
402 let reserved: u16 = cursor.read_bytes_le()?;
403 if reserved != 0 {
404 return Err(Error::InvalidPacket(
405 "the first two bytes of each WriteMemStackedAck SCD must be set to zero".into(),
406 ));
407 }
408 let length = cursor.read_bytes_le()?;
409 lengths.push(length);
410 to_read -= 4;
411 }
412
413 Ok(Self { lengths })
414 }
415}
416
417#[cfg(test)]
418mod tests {
419 use super::*;
420 use cameleon_impl::bytes_io::WriteBytes;
421
422 fn serialize_header(
423 status_code: u16,
424 command_id: u16,
425 scd_len: u16,
426 request_id: u16,
427 ) -> Vec<u8> {
428 let mut ccd = vec![];
429 ccd.write_bytes_le(0x4356_3355_u32).unwrap();
430 ccd.write_bytes_le(status_code).unwrap();
431 ccd.write_bytes_le(command_id).unwrap();
432 ccd.write_bytes_le(scd_len).unwrap();
433 ccd.write_bytes_le(request_id).unwrap();
434 ccd
435 }
436
437 #[test]
438 fn test_read_mem_ack() {
439 let scd = &[0x01, 0x02, 0x03, 0x04];
440 let mut raw_packet = serialize_header(0x0000, 0x0801, scd.len() as u16, 1);
441 raw_packet.extend(scd);
442
443 let ack = AckPacket::parse(&raw_packet).unwrap();
444 assert!(ack.status().is_success());
445 assert!(!ack.status().is_fatal());
446 assert_eq!(ack.request_id(), 1);
447
448 let parsed_scd = ack.scd_as::<ReadMem>().unwrap();
449 assert_eq!(parsed_scd.data, scd);
450 }
451
452 #[test]
453 fn test_write_mem_ack() {
454 let scd = &[0x00, 0x00, 0x0a, 0x00]; let mut raw_packet = serialize_header(0x0000, 0x0803, scd.len() as u16, 1);
456 raw_packet.extend(scd);
457
458 let ack = AckPacket::parse(&raw_packet).unwrap();
459 assert_eq!(ack.status().code(), 0x0000);
460 assert!(ack.status().is_success());
461 assert!(!ack.status().is_fatal());
462 assert_eq!(ack.request_id(), 1);
463
464 let parsed_scd = ack.scd_as::<WriteMem>().unwrap();
465 assert_eq!(parsed_scd.length, 0x0a);
466 }
467
468 #[test]
469 fn test_read_mem_stacked_ack() {
470 let scd = &[0x01, 0x02, 0x03, 0x04];
471 let mut raw_packet = serialize_header(0x0000, 0x0807, scd.len() as u16, 1);
472 raw_packet.extend(scd);
473
474 let ack = AckPacket::parse(&raw_packet).unwrap();
475 assert_eq!(ack.status().code(), 0x0000);
476 assert!(ack.status().is_success());
477 assert!(!ack.status().is_fatal());
478 assert_eq!(ack.request_id(), 1);
479
480 let parsed_scd = ack.scd_as::<ReadMemStacked>().unwrap();
481 assert_eq!(parsed_scd.data, scd);
482 }
483
484 #[test]
485 fn test_write_mem_stacked_ack() {
486 let mut scd = vec![0x00, 0x00, 0x03, 0x00]; scd.extend([0x00, 0x00, 0x0a, 0x00]); let mut raw_packet = serialize_header(0x0000, 0x0809, scd.len() as u16, 1);
489 raw_packet.extend(&scd);
490
491 let ack = AckPacket::parse(&raw_packet).unwrap();
492 assert_eq!(ack.status().code(), 0x0000);
493 assert!(ack.status().is_success());
494 assert!(!ack.status().is_fatal());
495 assert_eq!(ack.request_id(), 1);
496
497 let parsed_scd = ack.scd_as::<WriteMemStacked>().unwrap();
498 assert_eq!(&parsed_scd.lengths, &[3, 10]);
499 }
500
501 #[test]
502 fn test_pending_ack() {
503 use std::time::Duration;
504
505 let scd = &[0x00, 0x00, 0xbc, 0x02]; let mut raw_packet = serialize_header(0x0000, 0x0805, scd.len() as u16, 1);
507 raw_packet.extend(scd);
508
509 let ack = AckPacket::parse(&raw_packet).unwrap();
510 assert_eq!(ack.status().code(), 0x0000);
511 assert!(ack.status().is_success());
512 assert!(!ack.status().is_fatal());
513 assert_eq!(ack.request_id(), 1);
514
515 let parsed_scd = ack.scd_as::<Pending>().unwrap();
516 assert_eq!(parsed_scd.timeout, Duration::from_millis(700));
517 }
518
519 #[test]
520 fn test_gencp_error_status() {
521 let mut code_buf = vec![0; 2];
522
523 code_buf.as_mut_slice().write_bytes_le(0x800F_u16).unwrap();
524 let mut code = Cursor::new(code_buf.as_slice());
525 let status = Status::parse(&mut code).unwrap();
526 assert!(!status.is_success());
527 assert!(status.is_fatal());
528 }
529
530 #[test]
531 fn test_usb_error_status() {
532 let mut code_buf = vec![0; 2];
533
534 code_buf.as_mut_slice().write_bytes_le(0xA001_u16).unwrap();
535 let mut code = Cursor::new(code_buf.as_slice());
536 let status = Status::parse(&mut code).unwrap();
537 assert!(!status.is_success());
538 assert!(status.is_fatal());
539 match status.kind {
540 StatusKind::UsbSpecific(..) => {}
541 _ => panic!("must be USB specific error status"),
542 }
543 }
544}