1use embassy_usb_driver::EndpointType;
3
4use crate::builder::Config;
5use crate::driver::EndpointInfo;
6use crate::types::{InterfaceNumber, StringIndex};
7use crate::CONFIGURATION_VALUE;
8
9#[allow(missing_docs)]
11pub mod descriptor_type {
12 pub const DEVICE: u8 = 1;
13 pub const CONFIGURATION: u8 = 2;
14 pub const STRING: u8 = 3;
15 pub const INTERFACE: u8 = 4;
16 pub const ENDPOINT: u8 = 5;
17 pub const DEVICE_QUALIFIER: u8 = 6;
18 pub const OTHER_SPEED_CONFIGURATION: u8 = 7;
19 pub const IAD: u8 = 11;
20 pub const BOS: u8 = 15;
21 pub const CAPABILITY: u8 = 16;
22}
23
24pub mod lang_id {
26 pub const ENGLISH_US: u16 = 0x0409;
30}
31
32#[allow(missing_docs)]
34pub mod capability_type {
35 pub const WIRELESS_USB: u8 = 1;
36 pub const USB_2_0_EXTENSION: u8 = 2;
37 pub const SS_USB_DEVICE: u8 = 3;
38 pub const CONTAINER_ID: u8 = 4;
39 pub const PLATFORM: u8 = 5;
40}
41
42#[repr(u8)]
46#[derive(Copy, Clone, Eq, PartialEq, Debug)]
47#[cfg_attr(feature = "defmt", derive(defmt::Format))]
48pub enum SynchronizationType {
49 NoSynchronization = 0b00,
51 Asynchronous = 0b01,
53 Adaptive = 0b10,
55 Synchronous = 0b11,
57}
58
59#[repr(u8)]
63#[derive(Copy, Clone, Eq, PartialEq, Debug)]
64#[cfg_attr(feature = "defmt", derive(defmt::Format))]
65pub enum UsageType {
66 DataEndpoint = 0b00,
68 FeedbackEndpoint = 0b01,
70 ImplicitFeedbackDataEndpoint = 0b10,
72 Reserved = 0b11,
74}
75
76pub(crate) struct DescriptorWriter<'a> {
78 pub buf: &'a mut [u8],
79 position: usize,
80 num_interfaces_mark: Option<usize>,
81 num_endpoints_mark: Option<usize>,
82}
83
84impl<'a> DescriptorWriter<'a> {
85 pub(crate) fn new(buf: &'a mut [u8]) -> Self {
86 DescriptorWriter {
87 buf,
88 position: 0,
89 num_interfaces_mark: None,
90 num_endpoints_mark: None,
91 }
92 }
93
94 pub fn into_buf(self) -> &'a mut [u8] {
95 &mut self.buf[..self.position]
96 }
97
98 pub const fn position(&self) -> usize {
100 self.position
101 }
102
103 pub fn write(&mut self, descriptor_type: u8, descriptor: &[u8], extra_fields: &[u8]) {
105 let descriptor_length = descriptor.len();
106 let extra_fields_length = extra_fields.len();
107 let total_length = descriptor_length + extra_fields_length;
108
109 assert!(
110 (self.position + 2 + total_length) <= self.buf.len() && (total_length + 2) <= 255,
111 "Descriptor buffer full"
112 );
113
114 self.buf[self.position] = (total_length + 2) as u8;
115 self.buf[self.position + 1] = descriptor_type;
116
117 let start = self.position + 2;
118
119 self.buf[start..start + descriptor_length].copy_from_slice(descriptor);
120 self.buf[start + descriptor_length..start + total_length].copy_from_slice(extra_fields);
121
122 self.position = start + total_length;
123 }
124
125 pub(crate) fn configuration(&mut self, config: &Config) {
126 self.num_interfaces_mark = Some(self.position + 4);
127
128 self.write(
129 descriptor_type::CONFIGURATION,
130 &[
131 0,
132 0, 0, CONFIGURATION_VALUE, 0, 0x80 | if config.self_powered { 0x40 } else { 0x00 }
137 | if config.supports_remote_wakeup { 0x20 } else { 0x00 }, (config.max_power / 2) as u8, ],
140 &[],
141 );
142 }
143
144 #[allow(unused)]
145 pub(crate) fn end_class(&mut self) {
146 self.num_endpoints_mark = None;
147 }
148
149 pub(crate) fn end_configuration(&mut self) {
150 let position = self.position as u16;
151 self.buf[2..4].copy_from_slice(&position.to_le_bytes());
152 }
153
154 pub fn iad(
170 &mut self,
171 first_interface: InterfaceNumber,
172 interface_count: u8,
173 function_class: u8,
174 function_sub_class: u8,
175 function_protocol: u8,
176 ) {
177 self.write(
178 descriptor_type::IAD,
179 &[
180 first_interface.into(), interface_count, function_class,
183 function_sub_class,
184 function_protocol,
185 0,
186 ],
187 &[],
188 );
189 }
190
191 pub fn interface_alt(
206 &mut self,
207 number: InterfaceNumber,
208 alternate_setting: u8,
209 interface_class: u8,
210 interface_sub_class: u8,
211 interface_protocol: u8,
212 interface_string: Option<StringIndex>,
213 ) {
214 if alternate_setting == 0 {
215 match self.num_interfaces_mark {
216 Some(mark) => self.buf[mark] += 1,
217 None => {
218 panic!("you can only call `interface/interface_alt` after `configuration`.")
219 }
220 };
221 }
222
223 let str_index = interface_string.map_or(0, Into::into);
224
225 self.num_endpoints_mark = Some(self.position + 4);
226
227 self.write(
228 descriptor_type::INTERFACE,
229 &[
230 number.into(), alternate_setting, 0, interface_class, interface_sub_class, interface_protocol, str_index, ],
238 &[],
239 );
240 }
241
242 pub fn endpoint(
252 &mut self,
253 endpoint: &EndpointInfo,
254 synchronization_type: SynchronizationType,
255 usage_type: UsageType,
256 extra_fields: &[u8],
257 ) {
258 match self.num_endpoints_mark {
259 Some(mark) => self.buf[mark] += 1,
260 None => panic!("you can only call `endpoint` after `interface/interface_alt`."),
261 };
262
263 let mut bm_attributes = endpoint.ep_type as u8;
264
265 if endpoint.ep_type != EndpointType::Isochronous {
269 assert_eq!(synchronization_type, SynchronizationType::NoSynchronization);
270 assert_eq!(usage_type, UsageType::DataEndpoint);
271 } else {
272 if usage_type == UsageType::FeedbackEndpoint {
273 assert_eq!(synchronization_type, SynchronizationType::NoSynchronization)
274 }
275
276 let synchronization_bm_attibutes: u8 = (synchronization_type as u8) << 2;
277 let usage_bm_attibutes: u8 = (usage_type as u8) << 4;
278
279 bm_attributes |= usage_bm_attibutes | synchronization_bm_attibutes;
280 }
281
282 self.write(
283 descriptor_type::ENDPOINT,
284 &[
285 endpoint.addr.into(), bm_attributes, endpoint.max_packet_size as u8,
288 (endpoint.max_packet_size >> 8) as u8, endpoint.interval_ms, ],
291 extra_fields,
292 );
293 }
294
295 #[allow(unused)]
297 pub(crate) fn string(&mut self, string: &str) {
298 let mut pos = self.position;
299
300 assert!(pos + 2 <= self.buf.len(), "Descriptor buffer full");
301
302 self.buf[pos] = 0; self.buf[pos + 1] = descriptor_type::STRING;
304
305 pos += 2;
306
307 for c in string.encode_utf16() {
308 assert!(pos < self.buf.len(), "Descriptor buffer full");
309
310 self.buf[pos..pos + 2].copy_from_slice(&c.to_le_bytes());
311 pos += 2;
312 }
313
314 self.buf[self.position] = (pos - self.position) as u8;
315
316 self.position = pos;
317 }
318}
319
320pub(crate) fn device_descriptor(config: &Config) -> [u8; 18] {
325 [
326 18, 0x01, config.bcd_usb as u8,
329 (config.bcd_usb 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,
335 (config.vendor_id >> 8) as u8, config.product_id as u8,
337 (config.product_id >> 8) as u8, config.device_release as u8,
339 (config.device_release >> 8) as u8, config.manufacturer.map_or(0, |_| 1), config.product.map_or(0, |_| 2), config.serial_number.map_or(0, |_| 3), 1, ]
345}
346
347pub(crate) fn device_qualifier_descriptor(config: &Config) -> [u8; 10] {
352 [
353 10, 0x06, config.bcd_usb as u8,
356 (config.bcd_usb as u16 >> 8) as u8, config.device_class, config.device_sub_class, config.device_protocol, config.max_packet_size_0, 1, 0, ]
364}
365
366pub struct BosWriter<'a> {
368 pub(crate) writer: DescriptorWriter<'a>,
369 num_caps_mark: Option<usize>,
370}
371
372impl<'a> BosWriter<'a> {
373 pub(crate) const fn new(writer: DescriptorWriter<'a>) -> Self {
374 Self {
375 writer,
376 num_caps_mark: None,
377 }
378 }
379
380 pub(crate) fn bos(&mut self) {
381 if (self.writer.buf.len() - self.writer.position) < 5 {
382 return;
383 }
384 self.num_caps_mark = Some(self.writer.position + 4);
385 self.writer.write(
386 descriptor_type::BOS,
387 &[
388 0x00, 0x00, 0x00, ],
391 &[],
392 );
393
394 self.capability(capability_type::USB_2_0_EXTENSION, &[0; 4]);
395 }
396
397 pub fn capability(&mut self, capability_type: u8, data: &[u8]) {
404 match self.num_caps_mark {
405 Some(mark) => self.writer.buf[mark] += 1,
406 None => panic!("called `capability` not between `bos` and `end_bos`."),
407 }
408
409 let mut start = self.writer.position;
410 let blen = data.len();
411
412 assert!(
413 (start + blen + 3) <= self.writer.buf.len() && (blen + 3) <= 255,
414 "Descriptor buffer full"
415 );
416
417 self.writer.buf[start] = (blen + 3) as u8;
418 self.writer.buf[start + 1] = descriptor_type::CAPABILITY;
419 self.writer.buf[start + 2] = capability_type;
420
421 start += 3;
422 self.writer.buf[start..start + blen].copy_from_slice(data);
423 self.writer.position = start + blen;
424 }
425
426 pub(crate) fn end_bos(&mut self) {
427 if self.writer.position == 0 {
428 return;
429 }
430 self.num_caps_mark = None;
431 let position = self.writer.position as u16;
432 self.writer.buf[2..4].copy_from_slice(&position.to_le_bytes());
433 }
434}