1use anyhow::{Result, anyhow};
6use derive_more::{TryFrom, TryInto};
7use zerocopy::byteorder::little_endian::U16;
8use zerocopy::{FromBytes, Immutable, KnownLayout, Unaligned};
9
10#[derive(Copy, Clone, Eq, PartialEq, Debug, TryFrom, TryInto)]
11#[try_from(repr)]
12#[repr(u8)]
13pub enum DescriptorType {
14 Device = 1,
15 Configuration,
16 String,
17 Interface,
18 Endpoint,
19}
20
21#[derive(Copy, Clone, Eq, PartialEq, Debug, TryFrom, TryInto)]
22#[try_from(repr)]
23#[repr(u8)]
24pub enum TransferType {
25 Control,
26 Isochronous,
27 Bulk,
28 Interrupt,
29}
30
31#[derive(Copy, Clone, Eq, PartialEq, Debug)]
32pub enum Direction {
33 In,
34 Out,
35}
36
37#[derive(Clone, FromBytes, KnownLayout, Immutable, Unaligned, Debug)]
38#[repr(C)]
39pub struct DeviceDescriptor {
40 pub length: u8,
41 pub desc_type: u8,
42 pub usb_version: U16,
43 pub class: u8,
44 pub subclass: u8,
45 pub protocol: u8,
46 pub max_pkt_size: u8,
47 pub vendor_id: U16,
48 pub product_id: U16,
49 pub dev_version: U16,
50 pub manuf_idx: u8,
51 pub product_idx: u8,
52 pub serial_idx: u8,
53 pub num_config: u8,
54}
55
56pub struct Device<'a> {
57 bytes: &'a [u8],
58}
59
60impl<'a> Device<'a> {
61 pub fn new(bytes: &'a [u8]) -> Self {
62 Device { bytes }
63 }
64
65 pub fn as_bytes(&self) -> &'a [u8] {
67 self.bytes
68 }
69
70 pub fn descriptor(&self) -> Result<&'a DeviceDescriptor> {
72 DeviceDescriptor::ref_from_prefix(self.bytes)
73 .map(|(desc, _)| desc)
74 .map_err(|_err| anyhow!("Cannot parse device descriptor"))
75 }
76}
77
78#[derive(Clone, FromBytes, KnownLayout, Immutable, Unaligned, Debug)]
79#[repr(C)]
80pub struct ConfigurationDescriptor {
81 pub length: u8,
82 pub desc_type: u8,
83 pub tot_length: U16,
84 pub num_intf: u8,
85 pub config_val: u8,
86 pub str_idx: u8,
87 pub attr: u8,
88 pub max_power: u8,
89}
90
91impl ConfigurationDescriptor {
92 pub fn string_index(&self) -> Option<u8> {
93 if self.str_idx == 0 {
94 None
95 } else {
96 Some(self.str_idx)
97 }
98 }
99}
100
101#[derive(Clone, FromBytes, KnownLayout, Immutable, Unaligned, Debug)]
102#[repr(C)]
103pub struct InterfaceDescriptor {
104 pub length: u8,
105 pub desc_type: u8,
106 pub intf_num: u8,
107 pub alt_setting: u8,
108 pub num_ep: u8,
109 pub class: u8,
110 pub subclass: u8,
111 pub protocol: u8,
112 pub str_idx: u8,
113}
114
115impl InterfaceDescriptor {
116 pub fn string_index(&self) -> Option<u8> {
117 if self.str_idx == 0 {
118 None
119 } else {
120 Some(self.str_idx)
121 }
122 }
123}
124
125#[derive(Clone, FromBytes, KnownLayout, Immutable, Unaligned, Debug)]
126#[repr(C)]
127pub struct EndpointDescriptor {
128 pub length: u8,
129 pub desc_type: u8,
130 pub addr: u8,
131 pub attr: u8,
132 pub max_pkt_size: U16,
133 pub interval: u8,
134}
135
136impl EndpointDescriptor {
137 pub fn transfer_type(&self) -> TransferType {
138 (self.attr & 0x3).try_into().unwrap()
140 }
141
142 pub fn direction(&self) -> Direction {
143 if (self.addr & 0x80) == 0 {
144 Direction::Out
145 } else {
146 Direction::In
147 }
148 }
149}
150
151pub struct Configuration<'a> {
152 bytes: &'a [u8],
153}
154
155impl<'a> Configuration<'a> {
156 pub fn new(bytes: &'a [u8]) -> Self {
157 Configuration { bytes }
158 }
159
160 pub fn as_bytes(&self) -> &'a [u8] {
162 self.bytes
163 }
164
165 pub fn descriptor(&self) -> Result<&'a ConfigurationDescriptor> {
167 ConfigurationDescriptor::ref_from_prefix(self.bytes)
168 .map(|(desc, _)| desc)
169 .map_err(|_err| anyhow!("Cannot parse configuration descriptor"))
170 }
171
172 pub fn interface_alt_settings(&'a self) -> impl Iterator<Item = Interface<'a>> {
174 DescOffsetIter { bytes: self.bytes }.filter_map(|(_, desc_type, bytes)| {
175 if desc_type == DescriptorType::Interface as u8 {
176 Some(Interface { bytes })
177 } else {
178 None
179 }
180 })
181 }
182}
183
184struct DescOffsetIter<'a> {
185 bytes: &'a [u8],
186}
187
188impl<'a> Iterator for DescOffsetIter<'a> {
189 type Item = (usize, u8, &'a [u8]);
191
192 fn next(&mut self) -> Option<Self::Item> {
193 if self.bytes.len() < 2 {
195 None
196 } else {
197 let sz = self.bytes[0] as usize;
198 let next = Some((sz, self.bytes[1], self.bytes));
199 self.bytes = if sz < self.bytes.len() {
200 &self.bytes[sz..]
201 } else {
202 &[]
203 };
204 next
205 }
206 }
207}
208
209pub struct Interface<'a> {
210 bytes: &'a [u8],
211}
212
213impl<'a> Interface<'a> {
214 pub fn descriptor(&self) -> Result<&'a InterfaceDescriptor> {
216 InterfaceDescriptor::ref_from_prefix(self.bytes)
217 .map(|(desc, _)| desc)
218 .map_err(|_err| anyhow!("Cannot parse interface descriptor"))
219 }
220
221 fn subdescriptor_iter(&self) -> impl Iterator<Item = (usize, u8, &'a [u8])> {
222 DescOffsetIter { bytes: self.bytes }
223 .skip(1)
224 .take_while(|(_, desc_type, _)| {
225 *desc_type != DescriptorType::Interface as u8
227 })
228 }
229
230 pub fn endpoints(&self) -> impl Iterator<Item = Endpoint<'a>> {
232 self.subdescriptor_iter()
233 .filter_map(|(_, desc_type, bytes)| {
234 if desc_type == DescriptorType::Endpoint as u8 {
235 Some(Endpoint { bytes })
236 } else {
237 None
238 }
239 })
240 }
241
242 pub fn subdescriptors(&self) -> impl Iterator<Item = &'a [u8]> {
243 self.subdescriptor_iter().filter_map(|(sz, _, bytes)| {
244 if sz <= bytes.len() {
246 Some(&bytes[..sz])
247 } else {
248 None
249 }
250 })
251 }
252}
253
254pub struct Endpoint<'a> {
255 bytes: &'a [u8],
256}
257
258impl<'a> Endpoint<'a> {
259 pub fn descriptor(&self) -> Result<&'a EndpointDescriptor> {
260 EndpointDescriptor::ref_from_prefix(self.bytes)
261 .map(|(desc, _)| desc)
262 .map_err(|_err| anyhow!("Cannot parse endpoint descriptor"))
263 }
264}