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, UsbDevice, MAX_INTERFACE_COUNT, STRING_INDEX_CUSTOM_START};
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!("if composite_with_iads is set, you must set device_class = 0xEF, device_sub_class = 0x02, device_protocol = 0x01");
180 }
181
182 assert!(
183 config.max_power <= 500,
184 "The maximum allowed value for `max_power` is 500mA"
185 );
186
187 match config.max_packet_size_0 {
188 8 | 16 | 32 | 64 => {}
189 _ => panic!("invalid max_packet_size_0, the allowed values are 8, 16, 32 or 64"),
190 }
191
192 let mut config_descriptor = DescriptorWriter::new(config_descriptor_buf);
193 let mut bos_descriptor = BosWriter::new(DescriptorWriter::new(bos_descriptor_buf));
194
195 config_descriptor.configuration(&config);
196 bos_descriptor.bos();
197
198 Builder {
199 driver,
200 config,
201 interfaces: Vec::new(),
202 handlers: Vec::new(),
203 control_buf,
204 next_string_index: STRING_INDEX_CUSTOM_START,
205
206 config_descriptor,
207 bos_descriptor,
208
209 msos_descriptor: MsOsDescriptorWriter::new(msos_descriptor_buf),
210 }
211 }
212
213 pub fn build(mut self) -> UsbDevice<'d, D> {
215 let msos_descriptor = self.msos_descriptor.build(&mut self.bos_descriptor);
216
217 self.config_descriptor.end_configuration();
218 self.bos_descriptor.end_bos();
219
220 trace!("USB: config_descriptor used: {}", self.config_descriptor.position());
222 trace!("USB: bos_descriptor used: {}", self.bos_descriptor.writer.position());
223 trace!("USB: msos_descriptor used: {}", msos_descriptor.len());
224 trace!("USB: control_buf size: {}", self.control_buf.len());
225
226 UsbDevice::build(
227 self.driver,
228 self.config,
229 self.handlers,
230 self.config_descriptor.into_buf(),
231 self.bos_descriptor.writer.into_buf(),
232 msos_descriptor,
233 self.interfaces,
234 self.control_buf,
235 )
236 }
237
238 pub fn control_buf_len(&self) -> usize {
241 self.control_buf.len()
242 }
243
244 pub fn function(&mut self, class: u8, subclass: u8, protocol: u8) -> FunctionBuilder<'_, 'd, D> {
251 let first_interface = InterfaceNumber::new(self.interfaces.len() as u8);
252 let iface_count_index = if self.config.composite_with_iads {
253 self.config_descriptor
254 .iad(first_interface, 0, class, subclass, protocol);
255
256 Some(self.config_descriptor.position() - 5)
257 } else {
258 None
259 };
260
261 FunctionBuilder {
262 builder: self,
263 iface_count_index,
264
265 first_interface,
266 }
267 }
268
269 pub fn handler(&mut self, handler: &'d mut dyn Handler) {
274 assert!(
275 self.handlers.push(handler).is_ok(),
276 "embassy-usb: handler list full. Increase the `max_handler_count` compile-time setting. Current value: {}",
277 MAX_HANDLER_COUNT
278 );
279 }
280
281 pub fn string(&mut self) -> StringIndex {
283 let index = self.next_string_index;
284 self.next_string_index += 1;
285 StringIndex::new(index)
286 }
287
288 pub fn msos_descriptor(&mut self, windows_version: u32, vendor_code: u8) {
292 self.msos_descriptor.header(windows_version, vendor_code);
293 }
294
295 pub fn msos_feature<T: DeviceLevelDescriptor>(&mut self, desc: T) {
297 self.msos_descriptor.device_feature(desc);
298 }
299
300 pub fn msos_writer(&mut self) -> &mut MsOsDescriptorWriter<'d> {
303 &mut self.msos_descriptor
304 }
305}
306
307pub struct FunctionBuilder<'a, 'd, D: Driver<'d>> {
313 builder: &'a mut Builder<'d, D>,
314 iface_count_index: Option<usize>,
315
316 first_interface: InterfaceNumber,
317}
318
319impl<'a, 'd, D: Driver<'d>> Drop for FunctionBuilder<'a, 'd, D> {
320 fn drop(&mut self) {
321 self.builder.msos_descriptor.end_function();
322 }
323}
324
325impl<'a, 'd, D: Driver<'d>> FunctionBuilder<'a, 'd, D> {
326 pub fn interface(&mut self) -> InterfaceBuilder<'_, 'd, D> {
330 if let Some(i) = self.iface_count_index {
331 self.builder.config_descriptor.buf[i] += 1;
332 }
333
334 let number = self.builder.interfaces.len() as _;
335 let iface = Interface {
336 current_alt_setting: 0,
337 num_alt_settings: 0,
338 };
339
340 assert!(self.builder.interfaces.push(iface).is_ok(),
341 "embassy-usb: interface list full. Increase the `max_interface_count` compile-time setting. Current value: {}",
342 MAX_INTERFACE_COUNT
343 );
344
345 InterfaceBuilder {
346 builder: self.builder,
347 interface_number: InterfaceNumber::new(number),
348 next_alt_setting_number: 0,
349 }
350 }
351
352 pub fn msos_feature<T: FunctionLevelDescriptor>(&mut self, desc: T) {
354 if !self.builder.msos_descriptor.is_in_config_subset() {
355 self.builder.msos_descriptor.configuration(0);
356 }
357
358 if !self.builder.msos_descriptor.is_in_function_subset() {
359 self.builder.msos_descriptor.function(self.first_interface);
360 }
361
362 self.builder.msos_descriptor.function_feature(desc);
363 }
364}
365
366pub struct InterfaceBuilder<'a, 'd, D: Driver<'d>> {
368 builder: &'a mut Builder<'d, D>,
369 interface_number: InterfaceNumber,
370 next_alt_setting_number: u8,
371}
372
373impl<'a, 'd, D: Driver<'d>> InterfaceBuilder<'a, 'd, D> {
374 pub const fn interface_number(&self) -> InterfaceNumber {
376 self.interface_number
377 }
378
379 pub fn string(&mut self) -> StringIndex {
381 self.builder.string()
382 }
383
384 pub fn alt_setting(
390 &mut self,
391 class: u8,
392 subclass: u8,
393 protocol: u8,
394 interface_string: Option<StringIndex>,
395 ) -> InterfaceAltBuilder<'_, 'd, D> {
396 let number = self.next_alt_setting_number;
397 self.next_alt_setting_number += 1;
398 self.builder.interfaces[self.interface_number.0 as usize].num_alt_settings += 1;
399
400 self.builder.config_descriptor.interface_alt(
401 self.interface_number,
402 number,
403 class,
404 subclass,
405 protocol,
406 interface_string,
407 );
408
409 InterfaceAltBuilder {
410 builder: self.builder,
411 interface_number: self.interface_number,
412 alt_setting_number: number,
413 }
414 }
415}
416
417pub struct InterfaceAltBuilder<'a, 'd, D: Driver<'d>> {
419 builder: &'a mut Builder<'d, D>,
420 interface_number: InterfaceNumber,
421 alt_setting_number: u8,
422}
423
424impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
425 pub const fn interface_number(&self) -> InterfaceNumber {
427 self.interface_number
428 }
429
430 pub const fn alt_setting_number(&self) -> u8 {
432 self.alt_setting_number
433 }
434
435 pub fn descriptor(&mut self, descriptor_type: u8, descriptor: &[u8]) {
440 self.builder.config_descriptor.write(descriptor_type, descriptor, &[]);
441 }
442
443 pub fn bos_capability(&mut self, capability_type: u8, capability: &[u8]) {
445 self.builder.bos_descriptor.capability(capability_type, capability);
446 }
447
448 pub fn endpoint_descriptor(
454 &mut self,
455 endpoint: &EndpointInfo,
456 synchronization_type: SynchronizationType,
457 usage_type: UsageType,
458 extra_fields: &[u8],
459 ) {
460 self.builder
461 .config_descriptor
462 .endpoint(endpoint, synchronization_type, usage_type, extra_fields);
463 }
464
465 pub fn alloc_endpoint_in(
469 &mut self,
470 ep_type: EndpointType,
471 ep_addr: Option<EndpointAddress>,
472 max_packet_size: u16,
473 interval_ms: u8,
474 ) -> D::EndpointIn {
475 let ep = self
476 .builder
477 .driver
478 .alloc_endpoint_in(ep_type, ep_addr, max_packet_size, interval_ms)
479 .expect("alloc_endpoint_in failed");
480
481 ep
482 }
483
484 fn endpoint_in(
485 &mut self,
486 ep_type: EndpointType,
487 ep_addr: Option<EndpointAddress>,
488 max_packet_size: u16,
489 interval_ms: u8,
490 synchronization_type: SynchronizationType,
491 usage_type: UsageType,
492 extra_fields: &[u8],
493 ) -> D::EndpointIn {
494 let ep = self.alloc_endpoint_in(ep_type, ep_addr, max_packet_size, interval_ms);
495 self.endpoint_descriptor(ep.info(), synchronization_type, usage_type, extra_fields);
496
497 ep
498 }
499
500 pub fn alloc_endpoint_out(
504 &mut self,
505 ep_type: EndpointType,
506 ep_addr: Option<EndpointAddress>,
507 max_packet_size: u16,
508 interval_ms: u8,
509 ) -> D::EndpointOut {
510 let ep = self
511 .builder
512 .driver
513 .alloc_endpoint_out(ep_type, ep_addr, max_packet_size, interval_ms)
514 .expect("alloc_endpoint_out failed");
515
516 ep
517 }
518
519 fn endpoint_out(
520 &mut self,
521 ep_type: EndpointType,
522 ep_addr: Option<EndpointAddress>,
523 max_packet_size: u16,
524 interval_ms: u8,
525 synchronization_type: SynchronizationType,
526 usage_type: UsageType,
527 extra_fields: &[u8],
528 ) -> D::EndpointOut {
529 let ep = self.alloc_endpoint_out(ep_type, ep_addr, max_packet_size, interval_ms);
530 self.endpoint_descriptor(ep.info(), synchronization_type, usage_type, extra_fields);
531
532 ep
533 }
534
535 pub fn endpoint_bulk_in(&mut self, ep_addr: Option<EndpointAddress>, max_packet_size: u16) -> D::EndpointIn {
540 self.endpoint_in(
541 EndpointType::Bulk,
542 ep_addr,
543 max_packet_size,
544 0,
545 SynchronizationType::NoSynchronization,
546 UsageType::DataEndpoint,
547 &[],
548 )
549 }
550
551 pub fn endpoint_bulk_out(&mut self, ep_addr: Option<EndpointAddress>, max_packet_size: u16) -> D::EndpointOut {
556 self.endpoint_out(
557 EndpointType::Bulk,
558 ep_addr,
559 max_packet_size,
560 0,
561 SynchronizationType::NoSynchronization,
562 UsageType::DataEndpoint,
563 &[],
564 )
565 }
566
567 pub fn endpoint_interrupt_in(
572 &mut self,
573 ep_addr: Option<EndpointAddress>,
574 max_packet_size: u16,
575 interval_ms: u8,
576 ) -> D::EndpointIn {
577 self.endpoint_in(
578 EndpointType::Interrupt,
579 ep_addr,
580 max_packet_size,
581 interval_ms,
582 SynchronizationType::NoSynchronization,
583 UsageType::DataEndpoint,
584 &[],
585 )
586 }
587
588 pub fn endpoint_interrupt_out(
590 &mut self,
591 ep_addr: Option<EndpointAddress>,
592 max_packet_size: u16,
593 interval_ms: u8,
594 ) -> D::EndpointOut {
595 self.endpoint_out(
596 EndpointType::Interrupt,
597 ep_addr,
598 max_packet_size,
599 interval_ms,
600 SynchronizationType::NoSynchronization,
601 UsageType::DataEndpoint,
602 &[],
603 )
604 }
605
606 pub fn endpoint_isochronous_in(
611 &mut self,
612 ep_addr: Option<EndpointAddress>,
613 max_packet_size: u16,
614 interval_ms: u8,
615 synchronization_type: SynchronizationType,
616 usage_type: UsageType,
617 extra_fields: &[u8],
618 ) -> D::EndpointIn {
619 self.endpoint_in(
620 EndpointType::Isochronous,
621 ep_addr,
622 max_packet_size,
623 interval_ms,
624 synchronization_type,
625 usage_type,
626 extra_fields,
627 )
628 }
629
630 pub fn endpoint_isochronous_out(
632 &mut self,
633 ep_addr: Option<EndpointAddress>,
634 max_packet_size: u16,
635 interval_ms: u8,
636 synchronization_type: SynchronizationType,
637 usage_type: UsageType,
638 extra_fields: &[u8],
639 ) -> D::EndpointOut {
640 self.endpoint_out(
641 EndpointType::Isochronous,
642 ep_addr,
643 max_packet_size,
644 interval_ms,
645 synchronization_type,
646 usage_type,
647 extra_fields,
648 )
649 }
650}