1use core::cmp::min;
2
3use crate::bus::{InterfaceNumber, StringIndex, UsbBus};
4use crate::device;
5use crate::endpoint::{Endpoint, EndpointDirection};
6use crate::{Result, UsbError};
7
8#[allow(missing_docs)]
10pub mod descriptor_type {
11 pub const DEVICE: u8 = 1;
12 pub const CONFIGURATION: u8 = 2;
13 pub const STRING: u8 = 3;
14 pub const INTERFACE: u8 = 4;
15 pub const ENDPOINT: u8 = 5;
16 pub const IAD: u8 = 11;
17 pub const BOS: u8 = 15;
18 pub const CAPABILITY: u8 = 16;
19}
20
21pub mod lang_id;
23
24#[allow(missing_docs)]
26pub mod capability_type {
27 pub const WIRELESS_USB: u8 = 1;
28 pub const USB_2_0_EXTENSION: u8 = 2;
29 pub const SS_USB_DEVICE: u8 = 3;
30 pub const CONTAINER_ID: u8 = 4;
31 pub const PLATFORM: u8 = 5;
32}
33
34pub struct DescriptorWriter<'a> {
36 buf: &'a mut [u8],
37 position: usize,
38 num_interfaces_mark: Option<usize>,
39 num_endpoints_mark: Option<usize>,
40 write_iads: bool,
41}
42
43impl DescriptorWriter<'_> {
44 pub(crate) fn new(buf: &mut [u8]) -> DescriptorWriter<'_> {
45 DescriptorWriter {
46 buf,
47 position: 0,
48 num_interfaces_mark: None,
49 num_endpoints_mark: None,
50 write_iads: false,
51 }
52 }
53
54 pub fn position(&self) -> usize {
56 self.position
57 }
58
59 pub fn write(&mut self, descriptor_type: u8, descriptor: &[u8]) -> Result<()> {
61 self.write_with(descriptor_type, |buf| {
62 if descriptor.len() > buf.len() {
63 return Err(UsbError::BufferOverflow);
64 }
65
66 buf[..descriptor.len()].copy_from_slice(descriptor);
67
68 Ok(descriptor.len())
69 })
70 }
71
72 pub fn write_with(
79 &mut self,
80 descriptor_type: u8,
81 f: impl FnOnce(&mut [u8]) -> Result<usize>,
82 ) -> Result<()> {
83 if self.position + 2 > self.buf.len() {
84 return Err(UsbError::BufferOverflow);
85 }
86
87 let data_end = min(self.buf.len(), self.position + 256);
88 let data_buf = &mut self.buf[self.position + 2..data_end];
89
90 let total_len = f(data_buf)? + 2;
91
92 if self.position + total_len > self.buf.len() {
93 return Err(UsbError::BufferOverflow);
94 }
95
96 self.buf[self.position] = total_len as u8;
97 self.buf[self.position + 1] = descriptor_type;
98
99 self.position += total_len;
100
101 Ok(())
102 }
103
104 pub(crate) fn device(&mut self, config: &device::Config) -> Result<()> {
105 self.write(
106 descriptor_type::DEVICE,
107 &[
108 (config.usb_rev as u16) as u8,
109 (config.usb_rev as u16 >> 8) as u8, config.device_class, config.device_sub_class, config.device_protocol, config.max_packet_size_0, config.vendor_id as u8,
115 (config.vendor_id >> 8) as u8, config.product_id as u8,
117 (config.product_id >> 8) as u8, config.device_release as u8,
119 (config.device_release >> 8) as u8, config.string_descriptors.first().map_or(0, |lang| {
121 if lang.manufacturer.is_some() {
122 1
123 } else {
124 0
125 }
126 }),
127 config.string_descriptors.first().map_or(0, |lang| {
128 if lang.product.is_some() {
129 2
130 } else {
131 0
132 }
133 }),
134 config.string_descriptors.first().map_or(0, |lang| {
135 if lang.serial.is_some() {
136 3
137 } else {
138 0
139 }
140 }),
141 1, ],
143 )
144 }
145
146 pub(crate) fn configuration(&mut self, config: &device::Config) -> Result<()> {
147 self.num_interfaces_mark = Some(self.position + 4);
148
149 self.write_iads = config.composite_with_iads;
150
151 self.write(
152 descriptor_type::CONFIGURATION,
153 &[
154 0,
155 0, 0, device::CONFIGURATION_VALUE, 0, 0x80 | if config.self_powered { 0x40 } else { 0x00 }
160 | if config.supports_remote_wakeup {
161 0x20
162 } else {
163 0x00
164 }, config.max_power, ],
167 )
168 }
169
170 pub(crate) fn end_class(&mut self) {
171 self.num_endpoints_mark = None;
172 }
173
174 pub(crate) fn end_configuration(&mut self) {
175 let position = self.position as u16;
176 self.buf[2..4].copy_from_slice(&position.to_le_bytes());
177 }
178
179 pub fn iad(
196 &mut self,
197 first_interface: InterfaceNumber,
198 interface_count: u8,
199 function_class: u8,
200 function_sub_class: u8,
201 function_protocol: u8,
202 function_string: Option<StringIndex>,
203 ) -> Result<()> {
204 if !self.write_iads {
205 return Ok(());
206 }
207
208 let str_index = function_string.map_or(0, Into::into);
209
210 self.write(
211 descriptor_type::IAD,
212 &[
213 first_interface.into(), interface_count, function_class,
216 function_sub_class,
217 function_protocol,
218 str_index,
219 ],
220 )?;
221
222 Ok(())
223 }
224
225 pub fn interface(
236 &mut self,
237 number: InterfaceNumber,
238 interface_class: u8,
239 interface_sub_class: u8,
240 interface_protocol: u8,
241 ) -> Result<()> {
242 self.interface_alt(
243 number,
244 device::DEFAULT_ALTERNATE_SETTING,
245 interface_class,
246 interface_sub_class,
247 interface_protocol,
248 None,
249 )
250 }
251
252 pub fn interface_alt(
267 &mut self,
268 number: InterfaceNumber,
269 alternate_setting: u8,
270 interface_class: u8,
271 interface_sub_class: u8,
272 interface_protocol: u8,
273 interface_string: Option<StringIndex>,
274 ) -> Result<()> {
275 if alternate_setting == device::DEFAULT_ALTERNATE_SETTING {
276 match self.num_interfaces_mark {
277 Some(mark) => self.buf[mark] += 1,
278 None => return Err(UsbError::InvalidState),
279 };
280 }
281
282 let str_index = interface_string.map_or(0, Into::into);
283
284 self.num_endpoints_mark = Some(self.position + 4);
285
286 self.write(
287 descriptor_type::INTERFACE,
288 &[
289 number.into(), alternate_setting, 0, interface_class, interface_sub_class, interface_protocol, str_index, ],
297 )?;
298
299 Ok(())
300 }
301
302 pub fn endpoint<B: UsbBus, D: EndpointDirection>(
309 &mut self,
310 endpoint: &Endpoint<'_, B, D>,
311 ) -> Result<()> {
312 self.endpoint_ex(endpoint, |_| Ok(0))
313 }
314
315 pub fn endpoint_ex<B: UsbBus, D: EndpointDirection>(
327 &mut self,
328 endpoint: &Endpoint<'_, B, D>,
329 f: impl FnOnce(&mut [u8]) -> Result<usize>,
330 ) -> Result<()> {
331 match self.num_endpoints_mark {
332 Some(mark) => self.buf[mark] += 1,
333 None => return Err(UsbError::InvalidState),
334 };
335
336 self.write_with(descriptor_type::ENDPOINT, |buf| {
337 if buf.len() < 5 {
338 return Err(UsbError::BufferOverflow);
339 }
340
341 let mps = endpoint.max_packet_size();
342
343 buf[0] = endpoint.address().into();
344 buf[1] = endpoint.ep_type().to_bm_attributes();
345 buf[2] = mps as u8;
346 buf[3] = (mps >> 8) as u8;
347 buf[4] = endpoint.interval();
348
349 Ok(f(&mut buf[5..])? + 5)
350 })
351 }
352
353 pub(crate) fn string(&mut self, string: &str) -> Result<()> {
355 let mut pos = self.position;
356
357 if pos + 2 > self.buf.len() {
358 return Err(UsbError::BufferOverflow);
359 }
360
361 self.buf[pos] = 0; self.buf[pos + 1] = descriptor_type::STRING;
363
364 pos += 2;
365
366 for c in string.encode_utf16() {
367 if pos >= self.buf.len() {
368 return Err(UsbError::BufferOverflow);
369 }
370
371 self.buf[pos..pos + 2].copy_from_slice(&c.to_le_bytes());
372 pos += 2;
373 }
374
375 self.buf[self.position] = (pos - self.position) as u8;
376
377 self.position = pos;
378
379 Ok(())
380 }
381}
382
383pub struct BosWriter<'w, 'a: 'w> {
385 writer: &'w mut DescriptorWriter<'a>,
386 num_caps_mark: Option<usize>,
387}
388
389impl<'w, 'a: 'w> BosWriter<'w, 'a> {
390 pub(crate) fn new(writer: &'w mut DescriptorWriter<'a>) -> Self {
391 Self {
392 writer,
393 num_caps_mark: None,
394 }
395 }
396
397 pub(crate) fn bos(&mut self) -> Result<()> {
398 self.num_caps_mark = Some(self.writer.position + 4);
399 self.writer.write(
400 descriptor_type::BOS,
401 &[
402 0x00, 0x00, 0x00, ],
405 )?;
406
407 self.capability(capability_type::USB_2_0_EXTENSION, &[0; 4])?;
408
409 Ok(())
410 }
411
412 pub fn capability(&mut self, capability_type: u8, data: &[u8]) -> Result<()> {
419 match self.num_caps_mark {
420 Some(mark) => self.writer.buf[mark] += 1,
421 None => return Err(UsbError::InvalidState),
422 }
423
424 let mut start = self.writer.position;
425 let blen = data.len();
426
427 if (start + blen + 3) > self.writer.buf.len() || (blen + 3) > 255 {
428 return Err(UsbError::BufferOverflow);
429 }
430
431 self.writer.buf[start] = (blen + 3) as u8;
432 self.writer.buf[start + 1] = descriptor_type::CAPABILITY;
433 self.writer.buf[start + 2] = capability_type;
434
435 start += 3;
436 self.writer.buf[start..start + blen].copy_from_slice(data);
437 self.writer.position = start + blen;
438
439 Ok(())
440 }
441
442 pub(crate) fn end_bos(&mut self) {
443 self.num_caps_mark = None;
444 let position = self.writer.position as u16;
445 self.writer.buf[2..4].copy_from_slice(&position.to_le_bytes());
446 }
447}