1use heapless::Vec;
2
3use crate::config::MAX_HANDLER_COUNT;
4use crate::descriptor::{BosWriter, DescriptorWriter, SynchronizationType, UsageType};
5use crate::driver::{Driver, Endpoint, 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 info!("USB: config_descriptor used: {}", self.config_descriptor.position());
222 info!("USB: bos_descriptor used: {}", self.bos_descriptor.writer.position());
223 info!("USB: msos_descriptor used: {}", msos_descriptor.len());
224 info!("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(&mut self, ep_type: EndpointType, max_packet_size: u16, interval_ms: u8) -> D::EndpointIn {
469 let ep = self
470 .builder
471 .driver
472 .alloc_endpoint_in(ep_type, max_packet_size, interval_ms)
473 .expect("alloc_endpoint_in failed");
474
475 ep
476 }
477
478 fn endpoint_in(
479 &mut self,
480 ep_type: EndpointType,
481 max_packet_size: u16,
482 interval_ms: u8,
483 synchronization_type: SynchronizationType,
484 usage_type: UsageType,
485 extra_fields: &[u8],
486 ) -> D::EndpointIn {
487 let ep = self.alloc_endpoint_in(ep_type, max_packet_size, interval_ms);
488 self.endpoint_descriptor(ep.info(), synchronization_type, usage_type, extra_fields);
489
490 ep
491 }
492
493 pub fn alloc_endpoint_out(
497 &mut self,
498 ep_type: EndpointType,
499 max_packet_size: u16,
500 interval_ms: u8,
501 ) -> D::EndpointOut {
502 let ep = self
503 .builder
504 .driver
505 .alloc_endpoint_out(ep_type, max_packet_size, interval_ms)
506 .expect("alloc_endpoint_out failed");
507
508 ep
509 }
510
511 fn endpoint_out(
512 &mut self,
513 ep_type: EndpointType,
514 max_packet_size: u16,
515 interval_ms: u8,
516 synchronization_type: SynchronizationType,
517 usage_type: UsageType,
518 extra_fields: &[u8],
519 ) -> D::EndpointOut {
520 let ep = self.alloc_endpoint_out(ep_type, max_packet_size, interval_ms);
521 self.endpoint_descriptor(ep.info(), synchronization_type, usage_type, extra_fields);
522
523 ep
524 }
525
526 pub fn endpoint_bulk_in(&mut self, max_packet_size: u16) -> D::EndpointIn {
531 self.endpoint_in(
532 EndpointType::Bulk,
533 max_packet_size,
534 0,
535 SynchronizationType::NoSynchronization,
536 UsageType::DataEndpoint,
537 &[],
538 )
539 }
540
541 pub fn endpoint_bulk_out(&mut self, max_packet_size: u16) -> D::EndpointOut {
546 self.endpoint_out(
547 EndpointType::Bulk,
548 max_packet_size,
549 0,
550 SynchronizationType::NoSynchronization,
551 UsageType::DataEndpoint,
552 &[],
553 )
554 }
555
556 pub fn endpoint_interrupt_in(&mut self, max_packet_size: u16, interval_ms: u8) -> D::EndpointIn {
561 self.endpoint_in(
562 EndpointType::Interrupt,
563 max_packet_size,
564 interval_ms,
565 SynchronizationType::NoSynchronization,
566 UsageType::DataEndpoint,
567 &[],
568 )
569 }
570
571 pub fn endpoint_interrupt_out(&mut self, max_packet_size: u16, interval_ms: u8) -> D::EndpointOut {
573 self.endpoint_out(
574 EndpointType::Interrupt,
575 max_packet_size,
576 interval_ms,
577 SynchronizationType::NoSynchronization,
578 UsageType::DataEndpoint,
579 &[],
580 )
581 }
582
583 pub fn endpoint_isochronous_in(
588 &mut self,
589 max_packet_size: u16,
590 interval_ms: u8,
591 synchronization_type: SynchronizationType,
592 usage_type: UsageType,
593 extra_fields: &[u8],
594 ) -> D::EndpointIn {
595 self.endpoint_in(
596 EndpointType::Isochronous,
597 max_packet_size,
598 interval_ms,
599 synchronization_type,
600 usage_type,
601 extra_fields,
602 )
603 }
604
605 pub fn endpoint_isochronous_out(
607 &mut self,
608 max_packet_size: u16,
609 interval_ms: u8,
610 synchronization_type: SynchronizationType,
611 usage_type: UsageType,
612 extra_fields: &[u8],
613 ) -> D::EndpointOut {
614 self.endpoint_out(
615 EndpointType::Isochronous,
616 max_packet_size,
617 interval_ms,
618 synchronization_type,
619 usage_type,
620 extra_fields,
621 )
622 }
623}