aboutsummaryrefslogtreecommitdiff
path: root/embassy-usb/src/builder.rs
diff options
context:
space:
mode:
authoralexmoon <[email protected]>2023-02-02 16:13:16 -0500
committeralexmoon <[email protected]>2023-02-07 14:24:35 -0500
commit9f9230ae7abb545822e59c6f06cabb721b63e0a1 (patch)
tree0505e1793cef698a671a5b12f7567066a901eb7b /embassy-usb/src/builder.rs
parentb9ecdb72bb55792a8fa5a0bace8cdad498fee9b0 (diff)
Convert MS OS descriptor builder to a writer API
This brings it inline with the other embassy-usb descriptor APIs and allows it to integrate well with the Builder to allow class constructors to add MS OS descriptors. Also adds a `usb_serial_winusb` example to demonstrate how to use the API.
Diffstat (limited to 'embassy-usb/src/builder.rs')
-rw-r--r--embassy-usb/src/builder.rs78
1 files changed, 61 insertions, 17 deletions
diff --git a/embassy-usb/src/builder.rs b/embassy-usb/src/builder.rs
index 2c42fd64e..d1cbf674b 100644
--- a/embassy-usb/src/builder.rs
+++ b/embassy-usb/src/builder.rs
@@ -3,6 +3,8 @@ use heapless::Vec;
3use crate::control::ControlHandler; 3use crate::control::ControlHandler;
4use crate::descriptor::{BosWriter, DescriptorWriter}; 4use crate::descriptor::{BosWriter, DescriptorWriter};
5use crate::driver::{Driver, Endpoint, EndpointType}; 5use crate::driver::{Driver, Endpoint, EndpointType};
6#[cfg(feature = "msos-descriptor")]
7use crate::msos::{DeviceLevelDescriptor, FunctionLevelDescriptor, MsOsDescriptorWriter};
6use crate::types::*; 8use crate::types::*;
7use crate::{DeviceStateHandler, Interface, UsbDevice, MAX_INTERFACE_COUNT, STRING_INDEX_CUSTOM_START}; 9use crate::{DeviceStateHandler, Interface, UsbDevice, MAX_INTERFACE_COUNT, STRING_INDEX_CUSTOM_START};
8 10
@@ -130,7 +132,9 @@ pub struct Builder<'d, D: Driver<'d>> {
130 device_descriptor: DescriptorWriter<'d>, 132 device_descriptor: DescriptorWriter<'d>,
131 config_descriptor: DescriptorWriter<'d>, 133 config_descriptor: DescriptorWriter<'d>,
132 bos_descriptor: BosWriter<'d>, 134 bos_descriptor: BosWriter<'d>,
133 msos_descriptor: Option<crate::msos::MsOsDescriptorSet<'d>>, 135
136 #[cfg(feature = "msos-descriptor")]
137 msos_descriptor: MsOsDescriptorWriter<'d>,
134} 138}
135 139
136impl<'d, D: Driver<'d>> Builder<'d, D> { 140impl<'d, D: Driver<'d>> Builder<'d, D> {
@@ -145,6 +149,7 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
145 device_descriptor_buf: &'d mut [u8], 149 device_descriptor_buf: &'d mut [u8],
146 config_descriptor_buf: &'d mut [u8], 150 config_descriptor_buf: &'d mut [u8],
147 bos_descriptor_buf: &'d mut [u8], 151 bos_descriptor_buf: &'d mut [u8],
152 #[cfg(feature = "msos-descriptor")] msos_descriptor_buf: &'d mut [u8],
148 control_buf: &'d mut [u8], 153 control_buf: &'d mut [u8],
149 handler: Option<&'d dyn DeviceStateHandler>, 154 handler: Option<&'d dyn DeviceStateHandler>,
150 ) -> Self { 155 ) -> Self {
@@ -183,12 +188,17 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
183 device_descriptor, 188 device_descriptor,
184 config_descriptor, 189 config_descriptor,
185 bos_descriptor, 190 bos_descriptor,
186 msos_descriptor: None, 191
192 #[cfg(feature = "msos-descriptor")]
193 msos_descriptor: MsOsDescriptorWriter::new(msos_descriptor_buf),
187 } 194 }
188 } 195 }
189 196
190 /// Creates the [`UsbDevice`] instance with the configuration in this builder. 197 /// Creates the [`UsbDevice`] instance with the configuration in this builder.
191 pub fn build(mut self) -> UsbDevice<'d, D> { 198 pub fn build(mut self) -> UsbDevice<'d, D> {
199 #[cfg(feature = "msos-descriptor")]
200 let msos_descriptor = self.msos_descriptor.build(&mut self.bos_descriptor);
201
192 self.config_descriptor.end_configuration(); 202 self.config_descriptor.end_configuration();
193 self.bos_descriptor.end_bos(); 203 self.bos_descriptor.end_bos();
194 204
@@ -201,7 +211,8 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
201 self.bos_descriptor.writer.into_buf(), 211 self.bos_descriptor.writer.into_buf(),
202 self.interfaces, 212 self.interfaces,
203 self.control_buf, 213 self.control_buf,
204 self.msos_descriptor, 214 #[cfg(feature = "msos-descriptor")]
215 msos_descriptor,
205 ) 216 )
206 } 217 }
207 218
@@ -218,14 +229,10 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
218 /// 229 ///
219 /// If it's not set, no IAD descriptor is added. 230 /// If it's not set, no IAD descriptor is added.
220 pub fn function(&mut self, class: u8, subclass: u8, protocol: u8) -> FunctionBuilder<'_, 'd, D> { 231 pub fn function(&mut self, class: u8, subclass: u8, protocol: u8) -> FunctionBuilder<'_, 'd, D> {
232 let first_interface = InterfaceNumber::new(self.interfaces.len() as u8);
221 let iface_count_index = if self.config.composite_with_iads { 233 let iface_count_index = if self.config.composite_with_iads {
222 self.config_descriptor.iad( 234 self.config_descriptor
223 InterfaceNumber::new(self.interfaces.len() as _), 235 .iad(first_interface, 0, class, subclass, protocol);
224 0,
225 class,
226 subclass,
227 protocol,
228 );
229 236
230 Some(self.config_descriptor.position() - 5) 237 Some(self.config_descriptor.position() - 5)
231 } else { 238 } else {
@@ -235,19 +242,31 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
235 FunctionBuilder { 242 FunctionBuilder {
236 builder: self, 243 builder: self,
237 iface_count_index, 244 iface_count_index,
245
246 #[cfg(feature = "msos-descriptor")]
247 first_interface,
238 } 248 }
239 } 249 }
240 250
251 #[cfg(feature = "msos-descriptor")]
241 /// Add an MS OS 2.0 Descriptor Set. 252 /// Add an MS OS 2.0 Descriptor Set.
242 /// 253 ///
243 /// Panics if called more than once. 254 /// Panics if called more than once.
244 pub fn msos_descriptor(&mut self, msos_descriptor: crate::msos::MsOsDescriptorSet<'d>) { 255 pub fn msos_descriptor(&mut self, windows_version: u32, vendor_code: u8) {
245 if self.msos_descriptor.is_some() { 256 self.msos_descriptor.header(windows_version, vendor_code);
246 panic!("msos_descriptor already set"); 257 }
247 } 258
248 self.msos_descriptor 259 #[cfg(feature = "msos-descriptor")]
249 .insert(msos_descriptor) 260 /// Add an MS OS 2.0 Device Level Feature Descriptor.
250 .write_bos_capability(&mut self.bos_descriptor); 261 pub fn msos_feature<T: DeviceLevelDescriptor>(&mut self, desc: T) {
262 self.msos_descriptor.device_feature(desc);
263 }
264
265 #[cfg(feature = "msos-descriptor")]
266 /// Gets the underlying [`MsOsDescriptorWriter`] to allow adding subsets and features for classes that
267 /// do not add their own.
268 pub fn msos_writer(&mut self) -> &mut MsOsDescriptorWriter<'d> {
269 &mut self.msos_descriptor
251 } 270 }
252} 271}
253 272
@@ -259,6 +278,16 @@ impl<'d, D: Driver<'d>> Builder<'d, D> {
259pub struct FunctionBuilder<'a, 'd, D: Driver<'d>> { 278pub struct FunctionBuilder<'a, 'd, D: Driver<'d>> {
260 builder: &'a mut Builder<'d, D>, 279 builder: &'a mut Builder<'d, D>,
261 iface_count_index: Option<usize>, 280 iface_count_index: Option<usize>,
281
282 #[cfg(feature = "msos-descriptor")]
283 first_interface: InterfaceNumber,
284}
285
286impl<'a, 'd, D: Driver<'d>> Drop for FunctionBuilder<'a, 'd, D> {
287 fn drop(&mut self) {
288 #[cfg(feature = "msos-descriptor")]
289 self.builder.msos_descriptor.end_function();
290 }
262} 291}
263 292
264impl<'a, 'd, D: Driver<'d>> FunctionBuilder<'a, 'd, D> { 293impl<'a, 'd, D: Driver<'d>> FunctionBuilder<'a, 'd, D> {
@@ -288,6 +317,21 @@ impl<'a, 'd, D: Driver<'d>> FunctionBuilder<'a, 'd, D> {
288 next_alt_setting_number: 0, 317 next_alt_setting_number: 0,
289 } 318 }
290 } 319 }
320
321 #[cfg(feature = "msos-descriptor")]
322 /// Add an MS OS 2.0 Function Level Feature Descriptor.
323 pub fn msos_feature<T: FunctionLevelDescriptor>(&mut self, desc: T) {
324 if !self.builder.msos_descriptor.is_in_config_subset() {
325 self.builder.msos_descriptor.configuration(0);
326 }
327
328 if !self.builder.msos_descriptor.is_in_function_subset() {
329 self.builder.msos_descriptor.function(self.first_interface.0);
330 }
331
332 #[cfg(feature = "msos-descriptor")]
333 self.builder.msos_descriptor.function_feature(desc);
334 }
291} 335}
292 336
293/// Interface builder. 337/// Interface builder.