1use core::convert::TryFrom;
11
12#[derive(Clone, Copy, Debug, PartialEq)]
13pub enum DescriptorType {
14 Device = 1,
15 Configuration = 2,
16 String = 3,
17 Interface = 4,
18 Endpoint = 5,
19 DeviceQualifier = 6,
20 OtherSpeed = 7,
21 InterfacePower = 8,
22}
23
24impl TryFrom<u8> for DescriptorType {
25 type Error = &'static str;
26
27 fn try_from(v: u8) -> Result<Self, Self::Error> {
28 match v {
29 1 => Ok(Self::Device),
30 2 => Ok(Self::Configuration),
31 3 => Ok(Self::String),
32 4 => Ok(Self::Interface),
33 5 => Ok(Self::Endpoint),
34 6 => Ok(Self::DeviceQualifier),
35 7 => Ok(Self::OtherSpeed),
36 8 => Ok(Self::InterfacePower),
37 _ => Err("invalid descriptor"),
38 }
39 }
40}
41
42#[derive(Copy, Clone, Debug, PartialEq)]
43#[repr(C, packed)]
44pub struct DeviceDescriptor {
45 pub b_length: u8,
46 pub b_descriptor_type: DescriptorType,
47 pub bcd_usb: u16,
48 pub b_device_class: u8,
49 pub b_device_sub_class: u8,
50 pub b_device_protocol: u8,
51 pub b_max_packet_size: u8,
52 pub id_vendor: u16,
53 pub id_product: u16,
54 pub bcd_device: u16,
55 pub i_manufacturer: u8,
56 pub i_product: u8,
57 pub i_serial_number: u8,
58 pub b_num_configurations: u8,
59}
60
61#[derive(Copy, Clone, Debug, PartialEq)]
62#[repr(C, packed)]
63pub struct ConfigurationDescriptor {
64 pub b_length: u8,
65 pub b_descriptor_type: DescriptorType,
66 pub w_total_length: u16,
67 pub b_num_interfaces: u8,
68 pub b_configuration_value: u8,
69 pub i_configuration: u8,
70 pub bm_attributes: u8,
71 pub b_max_power: u8,
72}
73
74#[derive(Copy, Clone, Debug, PartialEq)]
75#[repr(C, packed)]
76pub struct InterfaceDescriptor {
77 pub b_length: u8,
78 pub b_descriptor_type: DescriptorType,
79 pub b_interface_number: u8,
80 pub b_alternate_setting: u8,
81 pub b_num_endpoints: u8,
82 pub b_interface_class: u8,
83 pub b_interface_sub_class: u8,
84 pub b_interface_protocol: u8,
85 pub i_interface: u8,
86}
87
88#[derive(Copy, Clone, Debug, PartialEq)]
89#[repr(C, packed)]
90pub struct EndpointDescriptor {
91 pub b_length: u8,
92 pub b_descriptor_type: DescriptorType,
93 pub b_endpoint_address: u8,
94 pub bm_attributes: u8,
95 pub w_max_packet_size: u16,
96 pub b_interval: u8,
97}
98
99#[cfg(test)]
100mod test {
101 use super::*;
102
103 use core::mem;
104 use core::slice;
105
106 #[test]
107 fn device_descriptor_layout() {
108 let len = mem::size_of::<DeviceDescriptor>();
109 assert_eq!(len, 18);
110 let desc = DeviceDescriptor {
111 b_length: len as u8,
112 b_descriptor_type: DescriptorType::Device,
113 bcd_usb: 0x1001,
114 b_device_class: 0xaa,
115 b_device_sub_class: 0xbb,
116 b_device_protocol: 0xcc,
117 b_max_packet_size: 0xdd,
118 id_vendor: 0xdead,
119 id_product: 0xbeef,
120 bcd_device: 0xf00d,
121 i_manufacturer: 0x11,
122 i_product: 0x22,
123 i_serial_number: 0x33,
124 b_num_configurations: 0x44,
125 };
126 let base = &desc as *const _ as usize;
127 assert_offset("b_length", &desc.b_length, base, 0x00);
128 assert_offset("b_descriptor_type", &desc.b_descriptor_type, base, 0x01);
129 assert_offset("bcd_usb", &desc.bcd_usb, base, 0x02);
130 assert_offset("b_device_class", &desc.b_device_class, base, 0x04);
131 assert_offset("b_device_sub_class", &desc.b_device_sub_class, base, 0x05);
132 assert_offset("b_device_protocol", &desc.b_device_protocol, base, 0x06);
133 assert_offset("b_max_packet_size", &desc.b_max_packet_size, base, 0x07);
134 assert_offset("id_vendor", &desc.id_vendor, base, 0x08);
135 assert_offset("id_product", &desc.id_product, base, 0x0a);
136 assert_offset("bcd_device", &desc.bcd_device, base, 0x0c);
137 assert_offset("i_manufacturer", &desc.i_manufacturer, base, 0x0e);
138 assert_offset("i_product", &desc.i_product, base, 0x0f);
139 assert_offset("i_serial_number", &desc.i_serial_number, base, 0x10);
140 assert_offset(
141 "b_num_configurations",
142 &desc.b_num_configurations,
143 base,
144 0x011,
145 );
146
147 let got = unsafe { slice::from_raw_parts(&desc as *const _ as *const u8, len) };
148 let want = &[
149 0x12, 0x01, 0x01, 0x10, 0xaa, 0xbb, 0xcc, 0xdd, 0xad, 0xde, 0xef, 0xbe, 0x0d, 0xf0,
150 0x11, 0x22, 0x33, 0x44,
151 ];
152 assert_eq!(got, want);
153 }
154
155 #[test]
156 fn configuration_descriptor_layout() {
157 let len = mem::size_of::<ConfigurationDescriptor>();
158 assert_eq!(len, 9);
159 let desc = ConfigurationDescriptor {
160 b_length: len as u8,
161 b_descriptor_type: DescriptorType::Configuration,
162 w_total_length: 0xdead,
163 b_num_interfaces: 0x22,
164 b_configuration_value: 0x33,
165 i_configuration: 0x44,
166 bm_attributes: 0x55,
167 b_max_power: 0x66,
168 };
169 let base = &desc as *const _ as usize;
170 assert_offset("b_length", &desc.b_length, base, 0x00);
171 assert_offset("b_descriptor_type", &desc.b_descriptor_type, base, 0x01);
172 assert_offset("w_total_length", &desc.w_total_length, base, 0x02);
173 assert_offset("b_num_interfaces", &desc.b_num_interfaces, base, 0x04);
174 assert_offset(
175 "b_configuration_value",
176 &desc.b_configuration_value,
177 base,
178 0x05,
179 );
180 assert_offset("i_configuration", &desc.i_configuration, base, 0x06);
181 assert_offset("bm_attributes", &desc.bm_attributes, base, 0x07);
182 assert_offset("b_max_power", &desc.b_max_power, base, 0x08);
183
184 let got = unsafe { slice::from_raw_parts(&desc as *const _ as *const u8, len) };
185 let want = &[0x09, 0x02, 0xad, 0xde, 0x22, 0x33, 0x44, 0x55, 0x66];
186 assert_eq!(got, want);
187 }
188
189 #[test]
190 fn interface_descriptor_layout() {
191 let len = mem::size_of::<InterfaceDescriptor>();
192 assert_eq!(len, 9);
193 let desc = InterfaceDescriptor {
194 b_length: len as u8,
195 b_descriptor_type: DescriptorType::Interface,
196 b_interface_number: 0xee,
197 b_alternate_setting: 0xaa,
198 b_num_endpoints: 0xf7,
199 b_interface_class: 0x11,
200 b_interface_sub_class: 0x22,
201 b_interface_protocol: 0x33,
202 i_interface: 0x44,
203 };
204 let base = &desc as *const _ as usize;
205 assert_offset("b_length", &desc.b_length, base, 0x00);
206 assert_offset("b_descriptor_type", &desc.b_descriptor_type, base, 0x01);
207 assert_offset("b_interface_number", &desc.b_interface_number, base, 0x02);
208 assert_offset("b_alternate_setting", &desc.b_alternate_setting, base, 0x03);
209 assert_offset("b_num_endpoints", &desc.b_num_endpoints, base, 0x04);
210 assert_offset("b_interface_class", &desc.b_interface_class, base, 0x05);
211 assert_offset(
212 "b_interface_sub_class",
213 &desc.b_interface_sub_class,
214 base,
215 0x06,
216 );
217 assert_offset(
218 "b_interface_protocol",
219 &desc.b_interface_protocol,
220 base,
221 0x07,
222 );
223 assert_offset("i_interface", &desc.i_interface, base, 0x08);
224
225 let got = unsafe { slice::from_raw_parts(&desc as *const _ as *const u8, len) };
226 let want = &[0x09, 0x04, 0xee, 0xaa, 0xf7, 0x11, 0x22, 0x33, 0x44];
227 assert_eq!(got, want);
228 }
229
230 #[test]
231 fn endpoint_descriptor_layout() {
232 let len = mem::size_of::<EndpointDescriptor>();
233 assert_eq!(len, 7);
234 let desc = EndpointDescriptor {
235 b_length: len as u8,
236 b_descriptor_type: DescriptorType::Endpoint,
237 b_endpoint_address: 2,
238 bm_attributes: 0xae,
239 w_max_packet_size: 0xdead,
240 b_interval: 0x7a,
241 };
242 let base = &desc as *const _ as usize;
243 assert_offset("b_length", &desc.b_length, base, 0x00);
244 assert_offset("b_descriptor_type", &desc.b_descriptor_type, base, 0x01);
245 assert_offset("b_endpoint_address", &desc.b_endpoint_address, base, 0x02);
246 assert_offset("bm_attributes", &desc.bm_attributes, base, 0x03);
247 assert_offset("w_max_packet_size", &desc.w_max_packet_size, base, 0x04);
248 assert_offset("b_interval", &desc.b_interval, base, 0x06);
249
250 let got = unsafe { slice::from_raw_parts(&desc as *const _ as *const u8, len) };
251 let want = &[0x07, 0x05, 0x02, 0xae, 0xad, 0xde, 0x7a];
252 assert_eq!(got, want);
253 }
254
255 fn assert_offset<T>(name: &str, field: &T, base: usize, offset: usize) {
256 let ptr = field as *const _ as usize;
257 assert_eq!(ptr - base, offset, "{} register offset.", name);
258 }
259}