xenet_packet/
usbpcap.rs

1//! A USB PCAP packet abstraction.
2
3use alloc::vec::Vec;
4
5use xenet_macro::Packet;
6use xenet_macro_helper::packet::PrimitiveValues;
7use xenet_macro_helper::types::{u1, u16le, u3, u32le, u4, u64le, u7};
8
9/// Represents a USB PCAP function for the requested operation.
10#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
11pub struct UsbPcapFunction(pub u16);
12
13impl UsbPcapFunction {
14    /// Construct a new `UsbPcapFunction` instance.
15    pub fn new(val: u16) -> Self {
16        Self(val)
17    }
18}
19
20impl PrimitiveValues for UsbPcapFunction {
21    type T = (u16,);
22    fn to_primitive_values(&self) -> Self::T {
23        (self.0,)
24    }
25}
26
27/// Represents the USB status for USB requests.
28#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
29pub struct UsbPcapStatus(pub u32);
30
31impl UsbPcapStatus {
32    /// Construct a new `UsbPcapStatus` instance.
33    pub fn new(val: u32) -> Self {
34        Self(val)
35    }
36}
37
38impl PrimitiveValues for UsbPcapStatus {
39    type T = (u32,);
40    fn to_primitive_values(&self) -> Self::T {
41        (self.0,)
42    }
43}
44
45/// Represents a USB PCAP packet ([Link Type 249](https://www.tcpdump.org/linktypes.html)).
46#[derive(Packet)]
47pub struct UsbPcap {
48    pub header_length: u16le,
49    pub irp_id: u64le,
50    #[construct_with(u32le)]
51    pub status: UsbPcapStatus,
52    #[construct_with(u16le)]
53    pub function: UsbPcapFunction,
54    pub reserved_info: u7,
55    pub pdo_to_fdo: u1,
56    pub bus: u16le,
57    pub device: u16le,
58    pub direction: u1,
59    pub reserved_endpoint: u3,
60    pub endpoint: u4,
61    pub transfer: u8,
62    pub data_length: u32le,
63    #[length = "header_length - 27"]
64    pub header_payload: Vec<u8>,
65    #[length = "data_length"]
66    #[payload]
67    pub payload: Vec<u8>,
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73    use xenet_macro_helper::packet::Packet;
74
75    #[test]
76    fn usbpcap_packet_test() {
77        let mut packet = [0u8; 35];
78        {
79            let mut usbpcap = MutableUsbPcapPacket::new(&mut packet[..]).unwrap();
80            usbpcap.set_header_length(27);
81            assert_eq!(usbpcap.get_header_length(), 27);
82
83            usbpcap.set_irp_id(0x12_34);
84            assert_eq!(usbpcap.get_irp_id(), 0x12_34);
85
86            usbpcap.set_status(UsbPcapStatus(30));
87            assert_eq!(usbpcap.get_status(), UsbPcapStatus(30));
88
89            usbpcap.set_function(UsbPcapFunction(40));
90            assert_eq!(usbpcap.get_function(), UsbPcapFunction(40));
91
92            assert_eq!(usbpcap.get_reserved_info(), 0);
93
94            usbpcap.set_pdo_to_fdo(1);
95            assert_eq!(usbpcap.get_pdo_to_fdo(), 1);
96
97            usbpcap.set_bus(60);
98            assert_eq!(usbpcap.get_bus(), 60);
99
100            usbpcap.set_device(70);
101            assert_eq!(usbpcap.get_device(), 70);
102
103            usbpcap.set_direction(1);
104            assert_eq!(usbpcap.get_direction(), 1);
105
106            assert_eq!(usbpcap.get_reserved_endpoint(), 0);
107
108            usbpcap.set_endpoint(14);
109            assert_eq!(usbpcap.get_endpoint(), 14);
110
111            usbpcap.set_transfer(80);
112            assert_eq!(usbpcap.get_transfer(), 80);
113
114            usbpcap.set_data_length(2);
115            assert_eq!(usbpcap.get_data_length(), 2);
116
117            assert_eq!(usbpcap.get_header_payload(), Vec::<u8>::new());
118
119            usbpcap.set_payload(&[90, 100]);
120            assert_eq!(usbpcap.payload(), &[90, 100]);
121        }
122
123        let ref_packet = [
124            27, 0, // Header length
125            0x34, 0x12, 0, 0, 0, 0, 0, 0, // IRP ID
126            30, 0, 0, 0, // Status
127            40, 0, // Function
128            1, // Info octet
129            60, 0, // Bus
130            70, 0,   // Device
131            142, // Endpoint fields
132            80,  // Transfer field
133            2, 0, 0, 0, // Data length field
134            // No header payload
135            90, 100, // Payload
136        ];
137
138        assert_eq!(&ref_packet[..], &packet[0..29]);
139    }
140
141    #[test]
142    fn usbpcap_packet_test_variable_header() {
143        let mut packet = [0u8; 35];
144        {
145            let mut usbpcap = MutableUsbPcapPacket::new(&mut packet[..]).unwrap();
146            usbpcap.set_header_length(28);
147            assert_eq!(usbpcap.get_header_length(), 28);
148
149            usbpcap.set_header_payload(&[110]);
150            assert_eq!(usbpcap.get_header_payload(), &[110]);
151
152            assert_eq!(usbpcap.payload(), Vec::<u8>::new());
153        }
154
155        let ref_packet = [
156            28, 0, // Header length
157            0, 0, 0, 0, 0, 0, 0, 0, // IRP ID
158            0, 0, 0, 0, // Status
159            0, 0, // Function
160            0, // Info
161            0, 0, // Bus
162            0, 0, // Device
163            0, // Endpoint fields
164            0, // Transfer field
165            0, 0, 0, 0, // Data length field
166            110, // Header payload
167               // No payload
168        ];
169
170        assert_eq!(&ref_packet[..], &packet[0..28]);
171    }
172}