1use heapless::Vec;
2
3use crate::config::MAX_HANDLER_COUNT;
4use crate::descriptor::{BosWriter, DescriptorWriter, SynchronizationType, UsageType};
5use crate::driver::{Driver, Endpoint, EndpointAddress, EndpointInfo, EndpointType};
6use crate::msos::{DeviceLevelDescriptor, FunctionLevelDescriptor, MsOsDescriptorWriter};
7use crate::types::{InterfaceNumber, StringIndex};
8use crate::{Handler, Interface, MAX_INTERFACE_COUNT, STRING_INDEX_CUSTOM_START, UsbDevice};
9
10#[derive(Debug, Copy, Clone)]
11#[cfg_attr(feature = "defmt", derive(defmt::Format))]
12#[non_exhaustive]
13pub enum UsbVersion {
15 Two = 0x0200,
17 TwoOne = 0x0210,
19}
20
21#[derive(Debug, Copy, Clone)]
22#[cfg_attr(feature = "defmt", derive(defmt::Format))]
23#[non_exhaustive]
24pub struct Config<'a> {
26 pub(crate) vendor_id: u16,
27 pub(crate) product_id: u16,
28
29 pub bcd_usb: UsbVersion,
33
34 pub device_class: u8,
40
41 pub device_sub_class: u8,
46
47 pub device_protocol: u8,
52
53 pub device_release: u16,
57
58 pub max_packet_size_0: u8,
67
68 pub manufacturer: Option<&'a str>,
72
73 pub product: Option<&'a str>,
77
78 pub serial_number: Option<&'a str>,
82
83 pub supports_remote_wakeup: bool,
87
88 pub composite_with_iads: bool,
99
100 pub self_powered: bool,
109
110 pub max_power: u16,
120}
121
122impl<'a> Config<'a> {
123 pub const fn new(vid: u16, pid: u16) -> Self {
125 Self {
126 device_class: 0xEF,
127 device_sub_class: 0x02,
128 device_protocol: 0x01,
129 max_packet_size_0: 64,
130 vendor_id: vid,
131 product_id: pid,
132 device_release: 0x0010,
133 bcd_usb: UsbVersion::TwoOne,
134 manufacturer: None,
135 product: None,
136 serial_number: None,
137 self_powered: false,
138 supports_remote_wakeup: false,
139 composite_with_iads: true,
140 max_power: 100,
141 }
142 }
143}
144
145pub struct Builder<'d, D: Driver<'d>> {
147 config: Config<'d>,
148 handlers: Vec<&'d mut dyn Handler, MAX_HANDLER_COUNT>,
149 interfaces: Vec<Interface, MAX_INTERFACE_COUNT>,
150 control_buf: &'d mut [u8],
151
152 driver: D,
153 next_string_index: u8,
154
155 config_descriptor: DescriptorWriter<'d>,
156 bos_descriptor: BosWriter<'d>,
157
158 msos_descriptor: MsOsDescriptorWriter<'d>,
159}
160
161impl<'d, D: Driver<'d>> Builder<'d, D> {
162 pub fn new(
168 driver: D,
169 config: Config<'d>,
170 config_descriptor_buf: &'d mut [u8],
171 bos_descriptor_buf: &'d mut [u8],
172 msos_descriptor_buf: &'d mut [u8],
173 control_buf: &'d mut [u8],
174 ) -> Self {
175 if config.composite_with_iads
177 && (config.device_class != 0xEF || config.device_sub_class != 0x02 || config.device_protocol != 0x01)
178 {
179 panic!(
180 "if composite_with_iads is set, you must set device_class = 0xEF, device_sub_class = 0x02, device_protocol = 0x01"
181 );
182 }
183
184 assert!(
185 config.max_power <= 500,
186 "The maximum allowed value for `max_power` is 500mA"
187 );
188
189 match config.max_packet_size_0 {
190 8 | 16 | 32 | 64 => {}
191 _ => panic!("invalid max_packet_size_0, the allowed values are 8, 16, 32 or 64"),
192 }
193
194 let mut config_descriptor = DescriptorWriter::new(config_descriptor_buf);
195 let mut bos_descriptor = BosWriter::new(DescriptorWriter::new(bos_descriptor_buf));
196
197 config_descriptor.configuration(&config);
198 bos_descriptor.bos();
199
200 Builder {
201 driver,
202 config,
203 interfaces: Vec::new(),
204 handlers: Vec::new(),
205 control_buf,
206 next_string_index: STRING_INDEX_CUSTOM_START,
207
208 config_descriptor,
209 bos_descriptor,
210
211 msos_descriptor: MsOsDescriptorWriter::new(msos_descriptor_buf),
212 }
213 }
214
215 pub fn build(mut self) -> UsbDevice<'d, D> {
217 let msos_descriptor = self.msos_descriptor.build(&mut self.bos_descriptor);
218
219 self.config_descriptor.end_configuration();
220 self.bos_descriptor.end_bos();
221
222 trace!("USB: config_descriptor used: {}", self.config_descriptor.position());
224 trace!("USB: bos_descriptor used: {}", self.bos_descriptor.writer.position());
225 trace!("USB: msos_descriptor used: {}", msos_descriptor.len());
226 trace!("USB: control_buf size: {}", self.control_buf.len());
227
228 UsbDevice::build(
229 self.driver,
230 self.config,
231 self.handlers,
232 self.config_descriptor.into_buf(),
233 self.bos_descriptor.writer.into_buf(),
234 msos_descriptor,
235 self.interfaces,
236 self.control_buf,
237 )
238 }
239
240 pub fn control_buf_len(&self) -> usize {
243 self.control_buf.len()
244 }
245
246 pub fn function(&mut self, class: u8, subclass: u8, protocol: u8) -> FunctionBuilder<'_, 'd, D> {
253 let first_interface = InterfaceNumber::new(self.interfaces.len() as u8);
254 let iface_count_index = if self.config.composite_with_iads {
255 self.config_descriptor
256 .iad(first_interface, 0, class, subclass, protocol);
257
258 Some(self.config_descriptor.position() - 5)
259 } else {
260 None
261 };
262
263 FunctionBuilder {
264 builder: self,
265 iface_count_index,
266
267 first_interface,
268 }
269 }
270
271 pub fn handler(&mut self, handler: &'d mut dyn Handler) {
276 assert!(
277 self.handlers.push(handler).is_ok(),
278 "embassy-usb: handler list full. Increase the `max_handler_count` compile-time setting. Current value: {}",
279 MAX_HANDLER_COUNT
280 );
281 }
282
283 pub fn string(&mut self) -> StringIndex {
285 let index = self.next_string_index;
286 self.next_string_index += 1;
287 StringIndex::new(index)
288 }
289
290 pub fn msos_descriptor(&mut self, windows_version: u32, vendor_code: u8) {
294 self.msos_descriptor.header(windows_version, vendor_code);
295 }
296
297 pub fn msos_feature<T: DeviceLevelDescriptor>(&mut self, desc: T) {
299 self.msos_descriptor.device_feature(desc);
300 }
301
302 pub fn msos_writer(&mut self) -> &mut MsOsDescriptorWriter<'d> {
305 &mut self.msos_descriptor
306 }
307}
308
309pub struct FunctionBuilder<'a, 'd, D: Driver<'d>> {
315 builder: &'a mut Builder<'d, D>,
316 iface_count_index: Option<usize>,
317
318 first_interface: InterfaceNumber,
319}
320
321impl<'a, 'd, D: Driver<'d>> Drop for FunctionBuilder<'a, 'd, D> {
322 fn drop(&mut self) {
323 self.builder.msos_descriptor.end_function();
324 }
325}
326
327impl<'a, 'd, D: Driver<'d>> FunctionBuilder<'a, 'd, D> {
328 pub fn interface(&mut self) -> InterfaceBuilder<'_, 'd, D> {
332 if let Some(i) = self.iface_count_index {
333 self.builder.config_descriptor.buf[i] += 1;
334 }
335
336 let number = self.builder.interfaces.len() as _;
337 let iface = Interface {
338 current_alt_setting: 0,
339 num_alt_settings: 0,
340 };
341
342 assert!(
343 self.builder.interfaces.push(iface).is_ok(),
344 "embassy-usb: interface list full. Increase the `max_interface_count` compile-time setting. Current value: {}",
345 MAX_INTERFACE_COUNT
346 );
347
348 InterfaceBuilder {
349 builder: self.builder,
350 interface_number: InterfaceNumber::new(number),
351 next_alt_setting_number: 0,
352 }
353 }
354
355 pub fn msos_feature<T: FunctionLevelDescriptor>(&mut self, desc: T) {
357 if !self.builder.msos_descriptor.is_in_config_subset() {
358 self.builder.msos_descriptor.configuration(0);
359 }
360
361 if !self.builder.msos_descriptor.is_in_function_subset() {
362 self.builder.msos_descriptor.function(self.first_interface);
363 }
364
365 self.builder.msos_descriptor.function_feature(desc);
366 }
367}
368
369pub struct InterfaceBuilder<'a, 'd, D: Driver<'d>> {
371 builder: &'a mut Builder<'d, D>,
372 interface_number: InterfaceNumber,
373 next_alt_setting_number: u8,
374}
375
376impl<'a, 'd, D: Driver<'d>> InterfaceBuilder<'a, 'd, D> {
377 pub const fn interface_number(&self) -> InterfaceNumber {
379 self.interface_number
380 }
381
382 pub fn string(&mut self) -> StringIndex {
384 self.builder.string()
385 }
386
387 pub fn alt_setting(
393 &mut self,
394 class: u8,
395 subclass: u8,
396 protocol: u8,
397 interface_string: Option<StringIndex>,
398 ) -> InterfaceAltBuilder<'_, 'd, D> {
399 let number = self.next_alt_setting_number;
400 self.next_alt_setting_number += 1;
401 self.builder.interfaces[self.interface_number.0 as usize].num_alt_settings += 1;
402
403 self.builder.config_descriptor.interface_alt(
404 self.interface_number,
405 number,
406 class,
407 subclass,
408 protocol,
409 interface_string,
410 );
411
412 InterfaceAltBuilder {
413 builder: self.builder,
414 interface_number: self.interface_number,
415 alt_setting_number: number,
416 }
417 }
418}
419
420pub struct InterfaceAltBuilder<'a, 'd, D: Driver<'d>> {
422 builder: &'a mut Builder<'d, D>,
423 interface_number: InterfaceNumber,
424 alt_setting_number: u8,
425}
426
427impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
428 pub const fn interface_number(&self) -> InterfaceNumber {
430 self.interface_number
431 }
432
433 pub const fn alt_setting_number(&self) -> u8 {
435 self.alt_setting_number
436 }
437
438 pub fn descriptor(&mut self, descriptor_type: u8, descriptor: &[u8]) {
443 self.builder.config_descriptor.write(descriptor_type, descriptor, &[]);
444 }
445
446 pub fn bos_capability(&mut self, capability_type: u8, capability: &[u8]) {
448 self.builder.bos_descriptor.capability(capability_type, capability);
449 }
450
451 pub fn endpoint_descriptor(
457 &mut self,
458 endpoint: &EndpointInfo,
459 synchronization_type: SynchronizationType,
460 usage_type: UsageType,
461 extra_fields: &[u8],
462 ) {
463 self.builder
464 .config_descriptor
465 .endpoint(endpoint, synchronization_type, usage_type, extra_fields);
466 }
467
468 pub fn alloc_endpoint_in(
472 &mut self,
473 ep_type: EndpointType,
474 ep_addr: Option<EndpointAddress>,
475 max_packet_size: u16,
476 interval_ms: u8,
477 ) -> D::EndpointIn {
478 let ep = self
479 .builder
480 .driver
481 .alloc_endpoint_in(ep_type, ep_addr, max_packet_size, interval_ms)
482 .expect("alloc_endpoint_in failed");
483
484 ep
485 }
486
487 fn endpoint_in(
488 &mut self,
489 ep_type: EndpointType,
490 ep_addr: Option<EndpointAddress>,
491 max_packet_size: u16,
492 interval_ms: u8,
493 synchronization_type: SynchronizationType,
494 usage_type: UsageType,
495 extra_fields: &[u8],
496 ) -> D::EndpointIn {
497 let ep = self.alloc_endpoint_in(ep_type, ep_addr, max_packet_size, interval_ms);
498 self.endpoint_descriptor(ep.info(), synchronization_type, usage_type, extra_fields);
499
500 ep
501 }
502
503 pub fn alloc_endpoint_out(
507 &mut self,
508 ep_type: EndpointType,
509 ep_addr: Option<EndpointAddress>,
510 max_packet_size: u16,
511 interval_ms: u8,
512 ) -> D::EndpointOut {
513 let ep = self
514 .builder
515 .driver
516 .alloc_endpoint_out(ep_type, ep_addr, max_packet_size, interval_ms)
517 .expect("alloc_endpoint_out failed");
518
519 ep
520 }
521
522 fn endpoint_out(
523 &mut self,
524 ep_type: EndpointType,
525 ep_addr: Option<EndpointAddress>,
526 max_packet_size: u16,
527 interval_ms: u8,
528 synchronization_type: SynchronizationType,
529 usage_type: UsageType,
530 extra_fields: &[u8],
531 ) -> D::EndpointOut {
532 let ep = self.alloc_endpoint_out(ep_type, ep_addr, max_packet_size, interval_ms);
533 self.endpoint_descriptor(ep.info(), synchronization_type, usage_type, extra_fields);
534
535 ep
536 }
537
538 pub fn endpoint_bulk_in(&mut self, ep_addr: Option<EndpointAddress>, max_packet_size: u16) -> D::EndpointIn {
543 self.endpoint_in(
544 EndpointType::Bulk,
545 ep_addr,
546 max_packet_size,
547 0,
548 SynchronizationType::NoSynchronization,
549 UsageType::DataEndpoint,
550 &[],
551 )
552 }
553
554 pub fn endpoint_bulk_out(&mut self, ep_addr: Option<EndpointAddress>, max_packet_size: u16) -> D::EndpointOut {
559 self.endpoint_out(
560 EndpointType::Bulk,
561 ep_addr,
562 max_packet_size,
563 0,
564 SynchronizationType::NoSynchronization,
565 UsageType::DataEndpoint,
566 &[],
567 )
568 }
569
570 pub fn endpoint_interrupt_in(
575 &mut self,
576 ep_addr: Option<EndpointAddress>,
577 max_packet_size: u16,
578 interval_ms: u8,
579 ) -> D::EndpointIn {
580 self.endpoint_in(
581 EndpointType::Interrupt,
582 ep_addr,
583 max_packet_size,
584 interval_ms,
585 SynchronizationType::NoSynchronization,
586 UsageType::DataEndpoint,
587 &[],
588 )
589 }
590
591 pub fn endpoint_interrupt_out(
593 &mut self,
594 ep_addr: Option<EndpointAddress>,
595 max_packet_size: u16,
596 interval_ms: u8,
597 ) -> D::EndpointOut {
598 self.endpoint_out(
599 EndpointType::Interrupt,
600 ep_addr,
601 max_packet_size,
602 interval_ms,
603 SynchronizationType::NoSynchronization,
604 UsageType::DataEndpoint,
605 &[],
606 )
607 }
608
609 pub fn endpoint_isochronous_in(
614 &mut self,
615 ep_addr: Option<EndpointAddress>,
616 max_packet_size: u16,
617 interval_ms: u8,
618 synchronization_type: SynchronizationType,
619 usage_type: UsageType,
620 extra_fields: &[u8],
621 ) -> D::EndpointIn {
622 self.endpoint_in(
623 EndpointType::Isochronous,
624 ep_addr,
625 max_packet_size,
626 interval_ms,
627 synchronization_type,
628 usage_type,
629 extra_fields,
630 )
631 }
632
633 pub fn endpoint_isochronous_out(
635 &mut self,
636 ep_addr: Option<EndpointAddress>,
637 max_packet_size: u16,
638 interval_ms: u8,
639 synchronization_type: SynchronizationType,
640 usage_type: UsageType,
641 extra_fields: &[u8],
642 ) -> D::EndpointOut {
643 self.endpoint_out(
644 EndpointType::Isochronous,
645 ep_addr,
646 max_packet_size,
647 interval_ms,
648 synchronization_type,
649 usage_type,
650 extra_fields,
651 )
652 }
653}