Skip to content

Commit 06d15e5

Browse files
committed
Make USB device config public
1 parent b6037b0 commit 06d15e5

File tree

4 files changed

+187
-23
lines changed

4 files changed

+187
-23
lines changed

src/config.rs

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
/// A USB vendor ID and product ID pair.
2+
pub struct UsbVidPid(pub u16, pub u16);
3+
4+
macro_rules! builder_fields {
5+
( $( $(#[$meta:meta])* $name:ident: $type:ty, )* ) => {
6+
$(
7+
$(#[$meta])*
8+
pub fn $name(mut self, $name: $type) -> Self {
9+
self.$name = $name;
10+
self
11+
}
12+
)*
13+
}
14+
}
15+
16+
/// A USB device configuration
17+
#[derive(Clone, Copy, Debug)]
18+
pub struct Config<'a> {
19+
/// USB device class
20+
pub device_class: u8,
21+
/// USB device subclass
22+
pub device_sub_class: u8,
23+
/// USB device protocol
24+
pub device_protocol: u8,
25+
/// USB control endpoint maximum packet size
26+
pub max_packet_size_0: u8,
27+
/// USB vendor ID
28+
pub vendor_id: u16,
29+
/// USB product ID
30+
pub product_id: u16,
31+
/// BCD encoded device release
32+
pub device_release: u16,
33+
/// Manufacturer string
34+
pub manufacturer: Option<&'a str>,
35+
/// Product string
36+
pub product: Option<&'a str>,
37+
/// Serial number
38+
pub serial_number: Option<&'a str>,
39+
/// Is device self-powered?
40+
pub self_powered: bool,
41+
/// Does device support remote wakeup?
42+
pub supports_remote_wakeup: bool,
43+
/// Is device composite with IADs?
44+
pub composite_with_iads: bool,
45+
/// Maximum power consumption of device
46+
pub max_power: u8,
47+
}
48+
49+
impl<'a> Config<'a> {
50+
51+
/// Create a USB device configuration with given vendor and product ID,
52+
/// using defaults.
53+
pub fn new(vid_pid: UsbVidPid) -> Self {
54+
Self {
55+
device_class: 0x00,
56+
device_sub_class: 0x00,
57+
device_protocol: 0x00,
58+
max_packet_size_0: 8,
59+
vendor_id: vid_pid.0,
60+
product_id: vid_pid.1,
61+
device_release: 0x0010,
62+
manufacturer: None,
63+
product: None,
64+
serial_number: None,
65+
self_powered: false,
66+
supports_remote_wakeup: false,
67+
composite_with_iads: false,
68+
max_power: 50,
69+
}
70+
}
71+
72+
builder_fields! {
73+
/// Sets the device class code assigned by USB.org. Set to `0xff` for vendor-specific
74+
/// devices that do not conform to any class.
75+
///
76+
/// Default: `0x00` (class code specified by interfaces)
77+
device_class: u8,
78+
79+
/// Sets the device sub-class code. Depends on class.
80+
///
81+
/// Default: `0x00`
82+
device_sub_class: u8,
83+
84+
/// Sets the device protocol code. Depends on class and sub-class.
85+
///
86+
/// Default: `0x00`
87+
device_protocol: u8,
88+
89+
/// Sets the device release version in BCD.
90+
///
91+
/// Default: `0x0010` ("0.1")
92+
device_release: u16,
93+
94+
/// Sets whether the device may have an external power source.
95+
///
96+
/// This should be set to `true` even if the device is sometimes self-powered and may not
97+
/// always draw power from the USB bus.
98+
///
99+
/// Default: `false`
100+
///
101+
/// See also: `max_power`
102+
self_powered: bool,
103+
104+
/// Sets whether the device supports remotely waking up the host is requested.
105+
///
106+
/// Default: `false`
107+
supports_remote_wakeup: bool,
108+
}
109+
110+
/// Configures the device as a composite device with interface association descriptors.
111+
pub fn composite_with_iads(mut self) -> Self {
112+
// Magic values specified in USB-IF ECN on IADs.
113+
self.device_class = 0xEF;
114+
self.device_sub_class = 0x02;
115+
self.device_protocol = 0x01;
116+
117+
self.composite_with_iads = true;
118+
self
119+
}
120+
121+
/// Sets the manufacturer name string descriptor.
122+
///
123+
/// Default: (none)
124+
pub fn manufacturer(mut self, manufacturer: &'a str) -> Self {
125+
self.manufacturer = Some(manufacturer);
126+
self
127+
}
128+
129+
/// Sets the product name string descriptor.
130+
///
131+
/// Default: (none)
132+
pub fn product(mut self, product: &'a str) -> Self {
133+
self.product = Some(product);
134+
self
135+
}
136+
137+
/// Sets the serial number string descriptor.
138+
///
139+
/// Default: (none)
140+
pub fn serial_number(mut self, serial_number: &'a str) -> Self {
141+
self.serial_number = Some(serial_number);
142+
self
143+
}
144+
145+
/// Sets the maximum packet size in bytes for the control endpoint 0.
146+
///
147+
/// Valid values are 8, 16, 32 and 64. There's generally no need to change this from the default
148+
/// value of 8 bytes unless a class uses control transfers for sending large amounts of data, in
149+
/// which case using a larger packet size may be more efficient.
150+
///
151+
/// Default: 8 bytes
152+
pub fn max_packet_size_0(mut self, max_packet_size_0: u8) -> Self {
153+
match max_packet_size_0 {
154+
8 | 16 | 32 | 64 => {}
155+
_ => panic!("invalid max_packet_size_0"),
156+
}
157+
158+
self.max_packet_size_0 = max_packet_size_0;
159+
self
160+
}
161+
162+
/// Sets the maximum current drawn from the USB bus by the device in milliamps.
163+
///
164+
/// The default is 100 mA. If your device always uses an external power source and never draws
165+
/// power from the USB bus, this can be set to 0.
166+
///
167+
/// See also: `self_powered`
168+
///
169+
/// Default: 100mA
170+
pub fn max_power(mut self, max_power_ma: usize) -> Self {
171+
if max_power_ma > 500 {
172+
panic!("max_power is too much")
173+
}
174+
175+
self.max_power = (max_power_ma / 2) as u8;
176+
self
177+
}
178+
}

src/device.rs

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use crate::bus::{PollResult, StringIndex, UsbBus, UsbBusAllocator};
22
use crate::class::{ControlIn, ControlOut, UsbClass};
3+
pub use crate::config::{Config, UsbVidPid};
34
use crate::control;
45
use crate::control_pipe::ControlPipe;
56
use crate::descriptor::{descriptor_type, lang_id, BosWriter, DescriptorWriter};
6-
pub use crate::device_builder::{UsbDeviceBuilder, UsbVidPid};
7+
pub use crate::device_builder::UsbDeviceBuilder;
78
use crate::endpoint::{EndpointAddress, EndpointType};
89
use crate::{Result, UsbDirection};
910

@@ -40,23 +41,6 @@ pub struct UsbDevice<'a, B: UsbBus> {
4041
pending_address: u8,
4142
}
4243

43-
pub(crate) struct Config<'a> {
44-
pub device_class: u8,
45-
pub device_sub_class: u8,
46-
pub device_protocol: u8,
47-
pub max_packet_size_0: u8,
48-
pub vendor_id: u16,
49-
pub product_id: u16,
50-
pub device_release: u16,
51-
pub manufacturer: Option<&'a str>,
52-
pub product: Option<&'a str>,
53-
pub serial_number: Option<&'a str>,
54-
pub self_powered: bool,
55-
pub supports_remote_wakeup: bool,
56-
pub composite_with_iads: bool,
57-
pub max_power: u8,
58-
}
59-
6044
/// The bConfiguration value for the not configured state.
6145
pub const CONFIGURATION_NONE: u8 = 0;
6246

@@ -69,7 +53,8 @@ pub const DEFAULT_ALTERNATE_SETTING: u8 = 0;
6953
type ClassList<'a, B> = [&'a mut dyn UsbClass<B>];
7054

7155
impl<B: UsbBus> UsbDevice<'_, B> {
72-
pub(crate) fn build<'a>(alloc: &'a UsbBusAllocator<B>, config: Config<'a>) -> UsbDevice<'a, B> {
56+
/// Build USB device with given allocator and configuration.
57+
pub fn build<'a>(alloc: &'a UsbBusAllocator<B>, config: Config<'a>) -> UsbDevice<'a, B> {
7358
let control_out = alloc
7459
.alloc(
7560
Some(0x00.into()),

src/device_builder.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
use crate::bus::{UsbBus, UsbBusAllocator};
2-
use crate::device::{Config, UsbDevice};
3-
4-
/// A USB vendor ID and product ID pair.
5-
pub struct UsbVidPid(pub u16, pub u16);
2+
pub use crate::config::UsbVidPid;
3+
use crate::{config::Config, device::UsbDevice};
64

75
/// Used to build new [`UsbDevice`]s.
86
pub struct UsbDeviceBuilder<'a, B: UsbBus> {

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ pub mod bus;
117117
/// and `write` to read and write data.
118118
pub mod class;
119119

120+
/// USB device configuration.
121+
pub mod config;
122+
120123
/// USB endpoints.
121124
pub mod endpoint;
122125

0 commit comments

Comments
 (0)