diff options
| author | alexmoon <[email protected]> | 2023-02-02 16:13:16 -0500 |
|---|---|---|
| committer | alexmoon <[email protected]> | 2023-02-07 14:24:35 -0500 |
| commit | 9f9230ae7abb545822e59c6f06cabb721b63e0a1 (patch) | |
| tree | 0505e1793cef698a671a5b12f7567066a901eb7b /embassy-usb/src/builder.rs | |
| parent | b9ecdb72bb55792a8fa5a0bace8cdad498fee9b0 (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.rs | 78 |
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; | |||
| 3 | use crate::control::ControlHandler; | 3 | use crate::control::ControlHandler; |
| 4 | use crate::descriptor::{BosWriter, DescriptorWriter}; | 4 | use crate::descriptor::{BosWriter, DescriptorWriter}; |
| 5 | use crate::driver::{Driver, Endpoint, EndpointType}; | 5 | use crate::driver::{Driver, Endpoint, EndpointType}; |
| 6 | #[cfg(feature = "msos-descriptor")] | ||
| 7 | use crate::msos::{DeviceLevelDescriptor, FunctionLevelDescriptor, MsOsDescriptorWriter}; | ||
| 6 | use crate::types::*; | 8 | use crate::types::*; |
| 7 | use crate::{DeviceStateHandler, Interface, UsbDevice, MAX_INTERFACE_COUNT, STRING_INDEX_CUSTOM_START}; | 9 | use 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 | ||
| 136 | impl<'d, D: Driver<'d>> Builder<'d, D> { | 140 | impl<'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> { | |||
| 259 | pub struct FunctionBuilder<'a, 'd, D: Driver<'d>> { | 278 | pub 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 | |||
| 286 | impl<'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 | ||
| 264 | impl<'a, 'd, D: Driver<'d>> FunctionBuilder<'a, 'd, D> { | 293 | impl<'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. |
