diff options
| author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-04-16 02:32:35 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-04-16 02:32:35 +0000 |
| commit | 0f1a364cd91148ab59773bf7aa43980f0ce6f04e (patch) | |
| tree | 0c1c6c54c60a5cf41ecd2353b92587d454e551f5 | |
| parent | 1c9adec3c59da48f8084c29b4ece083100a703e3 (diff) | |
| parent | 50d257cc7cb6f80118fc47a8c601db958775105c (diff) | |
Merge #720
720: USB: New builder API r=Dirbaio a=Dirbaio
usb: improved descriptor building API
The same API call allocates interfaces/endpoints/etc and writes their descriptors.
This means less API calls, and less possibility to screw things up.
DescriptorWriter is now private.
Co-authored-by: Dario Nieuwenhuis <[email protected]>
| -rw-r--r-- | embassy-usb-hid/src/lib.rs | 44 | ||||
| -rw-r--r-- | embassy-usb-serial/src/lib.rs | 53 | ||||
| -rw-r--r-- | embassy-usb/src/builder.rs | 331 | ||||
| -rw-r--r-- | embassy-usb/src/descriptor.rs | 39 | ||||
| -rw-r--r-- | embassy-usb/src/lib.rs | 2 | ||||
| -rw-r--r-- | examples/nrf/src/bin/usb_hid_keyboard.rs | 4 | ||||
| -rw-r--r-- | examples/nrf/src/bin/usb_hid_mouse.rs | 4 | ||||
| -rw-r--r-- | examples/nrf/src/bin/usb_serial.rs | 4 | ||||
| -rw-r--r-- | examples/nrf/src/bin/usb_serial_multitask.rs | 4 |
9 files changed, 233 insertions, 252 deletions
diff --git a/embassy-usb-hid/src/lib.rs b/embassy-usb-hid/src/lib.rs index abcd6b5d9..48e15e86a 100644 --- a/embassy-usb-hid/src/lib.rs +++ b/embassy-usb-hid/src/lib.rs | |||
| @@ -16,7 +16,7 @@ use embassy_usb::driver::EndpointOut; | |||
| 16 | use embassy_usb::{ | 16 | use embassy_usb::{ |
| 17 | control::{ControlHandler, InResponse, OutResponse, Request, RequestType}, | 17 | control::{ControlHandler, InResponse, OutResponse, Request, RequestType}, |
| 18 | driver::{Driver, Endpoint, EndpointError, EndpointIn}, | 18 | driver::{Driver, Endpoint, EndpointError, EndpointIn}, |
| 19 | UsbDeviceBuilder, | 19 | Builder, |
| 20 | }; | 20 | }; |
| 21 | 21 | ||
| 22 | #[cfg(feature = "usbd-hid")] | 22 | #[cfg(feature = "usbd-hid")] |
| @@ -98,7 +98,7 @@ pub struct HidReaderWriter<'d, D: Driver<'d>, const READ_N: usize, const WRITE_N | |||
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | fn build<'d, D: Driver<'d>>( | 100 | fn build<'d, D: Driver<'d>>( |
| 101 | builder: &mut UsbDeviceBuilder<'d, D>, | 101 | builder: &mut Builder<'d, D>, |
| 102 | state: &'d mut State<'d>, | 102 | state: &'d mut State<'d>, |
| 103 | config: Config<'d>, | 103 | config: Config<'d>, |
| 104 | with_out_endpoint: bool, | 104 | with_out_endpoint: bool, |
| @@ -110,23 +110,13 @@ fn build<'d, D: Driver<'d>>( | |||
| 110 | )); | 110 | )); |
| 111 | 111 | ||
| 112 | let len = config.report_descriptor.len(); | 112 | let len = config.report_descriptor.len(); |
| 113 | let if_num = builder.alloc_interface_with_handler(control); | ||
| 114 | let ep_in = builder.alloc_interrupt_endpoint_in(config.max_packet_size, config.poll_ms); | ||
| 115 | let ep_out = if with_out_endpoint { | ||
| 116 | Some(builder.alloc_interrupt_endpoint_out(config.max_packet_size, config.poll_ms)) | ||
| 117 | } else { | ||
| 118 | None | ||
| 119 | }; | ||
| 120 | 113 | ||
| 121 | builder.config_descriptor.interface( | 114 | let mut func = builder.function(USB_CLASS_HID, USB_SUBCLASS_NONE, USB_PROTOCOL_NONE); |
| 122 | if_num, | 115 | let mut iface = func.interface(Some(control)); |
| 123 | USB_CLASS_HID, | 116 | let mut alt = iface.alt_setting(USB_CLASS_HID, USB_SUBCLASS_NONE, USB_PROTOCOL_NONE); |
| 124 | USB_SUBCLASS_NONE, | ||
| 125 | USB_PROTOCOL_NONE, | ||
| 126 | ); | ||
| 127 | 117 | ||
| 128 | // HID descriptor | 118 | // HID descriptor |
| 129 | builder.config_descriptor.write( | 119 | alt.descriptor( |
| 130 | HID_DESC_DESCTYPE_HID, | 120 | HID_DESC_DESCTYPE_HID, |
| 131 | &[ | 121 | &[ |
| 132 | // HID Class spec version | 122 | // HID Class spec version |
| @@ -144,10 +134,12 @@ fn build<'d, D: Driver<'d>>( | |||
| 144 | ], | 134 | ], |
| 145 | ); | 135 | ); |
| 146 | 136 | ||
| 147 | builder.config_descriptor.endpoint(ep_in.info()); | 137 | let ep_in = alt.endpoint_interrupt_in(config.max_packet_size, config.poll_ms); |
| 148 | if let Some(ep_out) = &ep_out { | 138 | let ep_out = if with_out_endpoint { |
| 149 | builder.config_descriptor.endpoint(ep_out.info()); | 139 | Some(alt.endpoint_interrupt_out(config.max_packet_size, config.poll_ms)) |
| 150 | } | 140 | } else { |
| 141 | None | ||
| 142 | }; | ||
| 151 | 143 | ||
| 152 | (ep_out, ep_in, &state.out_report_offset) | 144 | (ep_out, ep_in, &state.out_report_offset) |
| 153 | } | 145 | } |
| @@ -160,11 +152,7 @@ impl<'d, D: Driver<'d>, const READ_N: usize, const WRITE_N: usize> | |||
| 160 | /// This will allocate one IN and one OUT endpoints. If you only need writing (sending) | 152 | /// This will allocate one IN and one OUT endpoints. If you only need writing (sending) |
| 161 | /// HID reports, consider using [`HidWriter::new`] instead, which allocates an IN endpoint only. | 153 | /// HID reports, consider using [`HidWriter::new`] instead, which allocates an IN endpoint only. |
| 162 | /// | 154 | /// |
| 163 | pub fn new( | 155 | pub fn new(builder: &mut Builder<'d, D>, state: &'d mut State<'d>, config: Config<'d>) -> Self { |
| 164 | builder: &mut UsbDeviceBuilder<'d, D>, | ||
| 165 | state: &'d mut State<'d>, | ||
| 166 | config: Config<'d>, | ||
| 167 | ) -> Self { | ||
| 168 | let (ep_out, ep_in, offset) = build(builder, state, config, true); | 156 | let (ep_out, ep_in, offset) = build(builder, state, config, true); |
| 169 | 157 | ||
| 170 | Self { | 158 | Self { |
| @@ -246,11 +234,7 @@ impl<'d, D: Driver<'d>, const N: usize> HidWriter<'d, D, N> { | |||
| 246 | /// HID reports. A lower value means better throughput & latency, at the expense | 234 | /// HID reports. A lower value means better throughput & latency, at the expense |
| 247 | /// of CPU on the device & bandwidth on the bus. A value of 10 is reasonable for | 235 | /// of CPU on the device & bandwidth on the bus. A value of 10 is reasonable for |
| 248 | /// high performance uses, and a value of 255 is good for best-effort usecases. | 236 | /// high performance uses, and a value of 255 is good for best-effort usecases. |
| 249 | pub fn new( | 237 | pub fn new(builder: &mut Builder<'d, D>, state: &'d mut State<'d>, config: Config<'d>) -> Self { |
| 250 | builder: &mut UsbDeviceBuilder<'d, D>, | ||
| 251 | state: &'d mut State<'d>, | ||
| 252 | config: Config<'d>, | ||
| 253 | ) -> Self { | ||
| 254 | let (ep_out, ep_in, _offset) = build(builder, state, config, false); | 238 | let (ep_out, ep_in, _offset) = build(builder, state, config, false); |
| 255 | 239 | ||
| 256 | assert!(ep_out.is_none()); | 240 | assert!(ep_out.is_none()); |
diff --git a/embassy-usb-serial/src/lib.rs b/embassy-usb-serial/src/lib.rs index 7b25398d0..4bddc31af 100644 --- a/embassy-usb-serial/src/lib.rs +++ b/embassy-usb-serial/src/lib.rs | |||
| @@ -11,7 +11,7 @@ use core::sync::atomic::{AtomicBool, Ordering}; | |||
| 11 | use embassy::blocking_mutex::CriticalSectionMutex; | 11 | use embassy::blocking_mutex::CriticalSectionMutex; |
| 12 | use embassy_usb::control::{self, ControlHandler, InResponse, OutResponse, Request}; | 12 | use embassy_usb::control::{self, ControlHandler, InResponse, OutResponse, Request}; |
| 13 | use embassy_usb::driver::{Endpoint, EndpointError, EndpointIn, EndpointOut}; | 13 | use embassy_usb::driver::{Endpoint, EndpointError, EndpointIn, EndpointOut}; |
| 14 | use embassy_usb::{driver::Driver, types::*, UsbDeviceBuilder}; | 14 | use embassy_usb::{driver::Driver, types::*, Builder}; |
| 15 | 15 | ||
| 16 | /// This should be used as `device_class` when building the `UsbDevice`. | 16 | /// This should be used as `device_class` when building the `UsbDevice`. |
| 17 | pub const USB_CLASS_CDC: u8 = 0x02; | 17 | pub const USB_CLASS_CDC: u8 = 0x02; |
| @@ -163,7 +163,7 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> { | |||
| 163 | /// Creates a new CdcAcmClass with the provided UsbBus and max_packet_size in bytes. For | 163 | /// Creates a new CdcAcmClass with the provided UsbBus and max_packet_size in bytes. For |
| 164 | /// full-speed devices, max_packet_size has to be one of 8, 16, 32 or 64. | 164 | /// full-speed devices, max_packet_size has to be one of 8, 16, 32 or 64. |
| 165 | pub fn new( | 165 | pub fn new( |
| 166 | builder: &mut UsbDeviceBuilder<'d, D>, | 166 | builder: &mut Builder<'d, D>, |
| 167 | state: &'d mut State<'d>, | 167 | state: &'d mut State<'d>, |
| 168 | max_packet_size: u16, | 168 | max_packet_size: u16, |
| 169 | ) -> Self { | 169 | ) -> Self { |
| @@ -175,26 +175,15 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> { | |||
| 175 | 175 | ||
| 176 | assert!(builder.control_buf_len() >= 7); | 176 | assert!(builder.control_buf_len() >= 7); |
| 177 | 177 | ||
| 178 | let comm_if = builder.alloc_interface_with_handler(control); | 178 | let mut func = builder.function(USB_CLASS_CDC, CDC_SUBCLASS_ACM, CDC_PROTOCOL_NONE); |
| 179 | let comm_ep = builder.alloc_interrupt_endpoint_in(8, 255); | 179 | |
| 180 | let data_if = builder.alloc_interface(); | 180 | // Control interface |
| 181 | let read_ep = builder.alloc_bulk_endpoint_out(max_packet_size); | 181 | let mut iface = func.interface(Some(control)); |
| 182 | let write_ep = builder.alloc_bulk_endpoint_in(max_packet_size); | 182 | let comm_if = iface.interface_number(); |
| 183 | 183 | let data_if = u8::from(comm_if) + 1; | |
| 184 | builder.config_descriptor.iad( | 184 | let mut alt = iface.alt_setting(USB_CLASS_CDC, CDC_SUBCLASS_ACM, CDC_PROTOCOL_NONE); |
| 185 | comm_if, | 185 | |
| 186 | 2, | 186 | alt.descriptor( |
| 187 | USB_CLASS_CDC, | ||
| 188 | CDC_SUBCLASS_ACM, | ||
| 189 | CDC_PROTOCOL_NONE, | ||
| 190 | ); | ||
| 191 | builder.config_descriptor.interface( | ||
| 192 | comm_if, | ||
| 193 | USB_CLASS_CDC, | ||
| 194 | CDC_SUBCLASS_ACM, | ||
| 195 | CDC_PROTOCOL_NONE, | ||
| 196 | ); | ||
| 197 | builder.config_descriptor.write( | ||
| 198 | CS_INTERFACE, | 187 | CS_INTERFACE, |
| 199 | &[ | 188 | &[ |
| 200 | CDC_TYPE_HEADER, // bDescriptorSubtype | 189 | CDC_TYPE_HEADER, // bDescriptorSubtype |
| @@ -202,14 +191,14 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> { | |||
| 202 | 0x01, // bcdCDC (1.10) | 191 | 0x01, // bcdCDC (1.10) |
| 203 | ], | 192 | ], |
| 204 | ); | 193 | ); |
| 205 | builder.config_descriptor.write( | 194 | alt.descriptor( |
| 206 | CS_INTERFACE, | 195 | CS_INTERFACE, |
| 207 | &[ | 196 | &[ |
| 208 | CDC_TYPE_ACM, // bDescriptorSubtype | 197 | CDC_TYPE_ACM, // bDescriptorSubtype |
| 209 | 0x00, // bmCapabilities | 198 | 0x00, // bmCapabilities |
| 210 | ], | 199 | ], |
| 211 | ); | 200 | ); |
| 212 | builder.config_descriptor.write( | 201 | alt.descriptor( |
| 213 | CS_INTERFACE, | 202 | CS_INTERFACE, |
| 214 | &[ | 203 | &[ |
| 215 | CDC_TYPE_UNION, // bDescriptorSubtype | 204 | CDC_TYPE_UNION, // bDescriptorSubtype |
| @@ -217,7 +206,7 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> { | |||
| 217 | data_if.into(), // bSubordinateInterface | 206 | data_if.into(), // bSubordinateInterface |
| 218 | ], | 207 | ], |
| 219 | ); | 208 | ); |
| 220 | builder.config_descriptor.write( | 209 | alt.descriptor( |
| 221 | CS_INTERFACE, | 210 | CS_INTERFACE, |
| 222 | &[ | 211 | &[ |
| 223 | CDC_TYPE_CALL_MANAGEMENT, // bDescriptorSubtype | 212 | CDC_TYPE_CALL_MANAGEMENT, // bDescriptorSubtype |
| @@ -225,13 +214,15 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> { | |||
| 225 | data_if.into(), // bDataInterface | 214 | data_if.into(), // bDataInterface |
| 226 | ], | 215 | ], |
| 227 | ); | 216 | ); |
| 228 | builder.config_descriptor.endpoint(comm_ep.info()); | ||
| 229 | 217 | ||
| 230 | builder | 218 | let comm_ep = alt.endpoint_interrupt_in(8, 255); |
| 231 | .config_descriptor | 219 | |
| 232 | .interface(data_if, USB_CLASS_CDC_DATA, 0x00, 0x00); | 220 | // Data interface |
| 233 | builder.config_descriptor.endpoint(write_ep.info()); | 221 | let mut iface = func.interface(None); |
| 234 | builder.config_descriptor.endpoint(read_ep.info()); | 222 | let data_if = iface.interface_number(); |
| 223 | let mut alt = iface.alt_setting(USB_CLASS_CDC_DATA, 0x00, CDC_PROTOCOL_NONE); | ||
| 224 | let read_ep = alt.endpoint_bulk_out(max_packet_size); | ||
| 225 | let write_ep = alt.endpoint_bulk_in(max_packet_size); | ||
| 235 | 226 | ||
| 236 | CdcAcmClass { | 227 | CdcAcmClass { |
| 237 | _comm_ep: comm_ep, | 228 | _comm_ep: comm_ep, |
diff --git a/embassy-usb/src/builder.rs b/embassy-usb/src/builder.rs index 486672055..7e67b4ae6 100644 --- a/embassy-usb/src/builder.rs +++ b/embassy-usb/src/builder.rs | |||
| @@ -2,7 +2,7 @@ use heapless::Vec; | |||
| 2 | 2 | ||
| 3 | use super::control::ControlHandler; | 3 | use super::control::ControlHandler; |
| 4 | use super::descriptor::{BosWriter, DescriptorWriter}; | 4 | use super::descriptor::{BosWriter, DescriptorWriter}; |
| 5 | use super::driver::{Driver, EndpointAllocError}; | 5 | use super::driver::{Driver, Endpoint}; |
| 6 | use super::types::*; | 6 | use super::types::*; |
| 7 | use super::DeviceStateHandler; | 7 | use super::DeviceStateHandler; |
| 8 | use super::UsbDevice; | 8 | use super::UsbDevice; |
| @@ -117,8 +117,8 @@ impl<'a> Config<'a> { | |||
| 117 | } | 117 | } |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | /// Used to build new [`UsbDevice`]s. | 120 | /// [`UsbDevice`] builder. |
| 121 | pub struct UsbDeviceBuilder<'d, D: Driver<'d>> { | 121 | pub struct Builder<'d, D: Driver<'d>> { |
| 122 | config: Config<'d>, | 122 | config: Config<'d>, |
| 123 | handler: Option<&'d dyn DeviceStateHandler>, | 123 | handler: Option<&'d dyn DeviceStateHandler>, |
| 124 | interfaces: Vec<(u8, &'d mut dyn ControlHandler), MAX_INTERFACE_COUNT>, | 124 | interfaces: Vec<(u8, &'d mut dyn ControlHandler), MAX_INTERFACE_COUNT>, |
| @@ -128,13 +128,12 @@ pub struct UsbDeviceBuilder<'d, D: Driver<'d>> { | |||
| 128 | next_interface_number: u8, | 128 | next_interface_number: u8, |
| 129 | next_string_index: u8, | 129 | next_string_index: u8, |
| 130 | 130 | ||
| 131 | // TODO make not pub? | 131 | device_descriptor: DescriptorWriter<'d>, |
| 132 | pub device_descriptor: DescriptorWriter<'d>, | 132 | config_descriptor: DescriptorWriter<'d>, |
| 133 | pub config_descriptor: DescriptorWriter<'d>, | 133 | bos_descriptor: BosWriter<'d>, |
| 134 | pub bos_descriptor: BosWriter<'d>, | ||
| 135 | } | 134 | } |
| 136 | 135 | ||
| 137 | impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> { | 136 | impl<'d, D: Driver<'d>> Builder<'d, D> { |
| 138 | /// Creates a builder for constructing a new [`UsbDevice`]. | 137 | /// Creates a builder for constructing a new [`UsbDevice`]. |
| 139 | /// | 138 | /// |
| 140 | /// `control_buf` is a buffer used for USB control request data. It should be sized | 139 | /// `control_buf` is a buffer used for USB control request data. It should be sized |
| @@ -175,7 +174,7 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> { | |||
| 175 | config_descriptor.configuration(&config); | 174 | config_descriptor.configuration(&config); |
| 176 | bos_descriptor.bos(); | 175 | bos_descriptor.bos(); |
| 177 | 176 | ||
| 178 | UsbDeviceBuilder { | 177 | Builder { |
| 179 | driver, | 178 | driver, |
| 180 | handler, | 179 | handler, |
| 181 | config, | 180 | config, |
| @@ -207,36 +206,12 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> { | |||
| 207 | ) | 206 | ) |
| 208 | } | 207 | } |
| 209 | 208 | ||
| 210 | /// Allocates a new interface number. | ||
| 211 | pub fn alloc_interface(&mut self) -> InterfaceNumber { | ||
| 212 | let number = self.next_interface_number; | ||
| 213 | self.next_interface_number += 1; | ||
| 214 | |||
| 215 | InterfaceNumber::new(number) | ||
| 216 | } | ||
| 217 | |||
| 218 | /// Returns the size of the control request data buffer. Can be used by | 209 | /// Returns the size of the control request data buffer. Can be used by |
| 219 | /// classes to validate the buffer is large enough for their needs. | 210 | /// classes to validate the buffer is large enough for their needs. |
| 220 | pub fn control_buf_len(&self) -> usize { | 211 | pub fn control_buf_len(&self) -> usize { |
| 221 | self.control_buf.len() | 212 | self.control_buf.len() |
| 222 | } | 213 | } |
| 223 | 214 | ||
| 224 | /// Allocates a new interface number, with a handler that will be called | ||
| 225 | /// for all the control requests directed to it. | ||
| 226 | pub fn alloc_interface_with_handler( | ||
| 227 | &mut self, | ||
| 228 | handler: &'d mut dyn ControlHandler, | ||
| 229 | ) -> InterfaceNumber { | ||
| 230 | let number = self.next_interface_number; | ||
| 231 | self.next_interface_number += 1; | ||
| 232 | |||
| 233 | if self.interfaces.push((number, handler)).is_err() { | ||
| 234 | panic!("max class count reached") | ||
| 235 | } | ||
| 236 | |||
| 237 | InterfaceNumber::new(number) | ||
| 238 | } | ||
| 239 | |||
| 240 | /// Allocates a new string index. | 215 | /// Allocates a new string index. |
| 241 | pub fn alloc_string(&mut self) -> StringIndex { | 216 | pub fn alloc_string(&mut self) -> StringIndex { |
| 242 | let index = self.next_string_index; | 217 | let index = self.next_string_index; |
| @@ -245,146 +220,212 @@ impl<'d, D: Driver<'d>> UsbDeviceBuilder<'d, D> { | |||
| 245 | StringIndex::new(index) | 220 | StringIndex::new(index) |
| 246 | } | 221 | } |
| 247 | 222 | ||
| 248 | /// Allocates an in endpoint. | 223 | /// Add an USB function. |
| 249 | /// | 224 | /// |
| 250 | /// This directly delegates to [`Driver::alloc_endpoint_in`], so see that method for details. In most | 225 | /// If [`Config::composite_with_iads`] is set, this will add an IAD descriptor |
| 251 | /// cases classes should call the endpoint type specific methods instead. | 226 | /// with the given class/subclass/protocol, associating all the child interfaces. |
| 252 | pub fn alloc_endpoint_in( | 227 | /// |
| 228 | /// If it's not set, no IAD descriptor is added. | ||
| 229 | pub fn function( | ||
| 253 | &mut self, | 230 | &mut self, |
| 254 | ep_addr: Option<EndpointAddress>, | 231 | class: u8, |
| 255 | ep_type: EndpointType, | 232 | subclass: u8, |
| 256 | max_packet_size: u16, | 233 | protocol: u8, |
| 257 | interval: u8, | 234 | ) -> FunctionBuilder<'_, 'd, D> { |
| 258 | ) -> Result<D::EndpointIn, EndpointAllocError> { | 235 | let iface_count_index = if self.config.composite_with_iads { |
| 259 | self.driver | 236 | self.config_descriptor.iad( |
| 260 | .alloc_endpoint_in(ep_addr, ep_type, max_packet_size, interval) | 237 | InterfaceNumber::new(self.next_interface_number), |
| 238 | 0, | ||
| 239 | class, | ||
| 240 | subclass, | ||
| 241 | protocol, | ||
| 242 | ); | ||
| 243 | |||
| 244 | Some(self.config_descriptor.position() - 5) | ||
| 245 | } else { | ||
| 246 | None | ||
| 247 | }; | ||
| 248 | |||
| 249 | FunctionBuilder { | ||
| 250 | builder: self, | ||
| 251 | iface_count_index, | ||
| 252 | } | ||
| 261 | } | 253 | } |
| 254 | } | ||
| 255 | |||
| 256 | /// Function builder. | ||
| 257 | /// | ||
| 258 | /// A function is a logical grouping of interfaces that perform a given USB function. | ||
| 259 | /// If [`Config::composite_with_iads`] is set, each function will have an IAD descriptor. | ||
| 260 | /// If not, functions will not be visible as descriptors. | ||
| 261 | pub struct FunctionBuilder<'a, 'd, D: Driver<'d>> { | ||
| 262 | builder: &'a mut Builder<'d, D>, | ||
| 263 | iface_count_index: Option<usize>, | ||
| 264 | } | ||
| 262 | 265 | ||
| 263 | /// Allocates an out endpoint. | 266 | impl<'a, 'd, D: Driver<'d>> FunctionBuilder<'a, 'd, D> { |
| 267 | /// Add an interface to the function. | ||
| 264 | /// | 268 | /// |
| 265 | /// This directly delegates to [`Driver::alloc_endpoint_out`], so see that method for details. In most | 269 | /// Interface numbers are guaranteed to be allocated consecutively, starting from 0. |
| 266 | /// cases classes should call the endpoint type specific methods instead. | 270 | pub fn interface( |
| 267 | pub fn alloc_endpoint_out( | ||
| 268 | &mut self, | 271 | &mut self, |
| 269 | ep_addr: Option<EndpointAddress>, | 272 | handler: Option<&'d mut dyn ControlHandler>, |
| 270 | ep_type: EndpointType, | 273 | ) -> InterfaceBuilder<'_, 'd, D> { |
| 271 | max_packet_size: u16, | 274 | if let Some(i) = self.iface_count_index { |
| 272 | interval: u8, | 275 | self.builder.config_descriptor.buf[i] += 1; |
| 273 | ) -> Result<D::EndpointOut, EndpointAllocError> { | 276 | } |
| 274 | self.driver | 277 | |
| 275 | .alloc_endpoint_out(ep_addr, ep_type, max_packet_size, interval) | 278 | let number = self.builder.next_interface_number; |
| 279 | self.builder.next_interface_number += 1; | ||
| 280 | |||
| 281 | if let Some(handler) = handler { | ||
| 282 | if self.builder.interfaces.push((number, handler)).is_err() { | ||
| 283 | panic!("max interface count reached") | ||
| 284 | } | ||
| 285 | } | ||
| 286 | |||
| 287 | InterfaceBuilder { | ||
| 288 | builder: self.builder, | ||
| 289 | interface_number: InterfaceNumber::new(number), | ||
| 290 | next_alt_setting_number: 0, | ||
| 291 | } | ||
| 276 | } | 292 | } |
| 293 | } | ||
| 277 | 294 | ||
| 278 | /// Allocates a control in endpoint. | 295 | /// Interface builder. |
| 279 | /// | 296 | pub struct InterfaceBuilder<'a, 'd, D: Driver<'d>> { |
| 280 | /// This crate implements the control state machine only for endpoint 0. If classes want to | 297 | builder: &'a mut Builder<'d, D>, |
| 281 | /// support control requests in other endpoints, the state machine must be implemented manually. | 298 | interface_number: InterfaceNumber, |
| 282 | /// This should rarely be needed by classes. | 299 | next_alt_setting_number: u8, |
| 283 | /// | 300 | } |
| 284 | /// # Arguments | 301 | |
| 285 | /// | 302 | impl<'a, 'd, D: Driver<'d>> InterfaceBuilder<'a, 'd, D> { |
| 286 | /// * `max_packet_size` - Maximum packet size in bytes. Must be one of 8, 16, 32 or 64. | 303 | /// Get the interface number. |
| 287 | /// | 304 | pub fn interface_number(&self) -> InterfaceNumber { |
| 288 | /// # Panics | 305 | self.interface_number |
| 289 | /// | ||
| 290 | /// Panics if endpoint allocation fails, because running out of endpoints or memory is not | ||
| 291 | /// feasibly recoverable. | ||
| 292 | #[inline] | ||
| 293 | pub fn alloc_control_endpoint_in(&mut self, max_packet_size: u16) -> D::EndpointIn { | ||
| 294 | self.alloc_endpoint_in(None, EndpointType::Control, max_packet_size, 0) | ||
| 295 | .expect("alloc_ep failed") | ||
| 296 | } | 306 | } |
| 297 | 307 | ||
| 298 | /// Allocates a control out endpoint. | 308 | /// Add an alternate setting to the interface and write its descriptor. |
| 299 | /// | ||
| 300 | /// This crate implements the control state machine only for endpoint 0. If classes want to | ||
| 301 | /// support control requests in other endpoints, the state machine must be implemented manually. | ||
| 302 | /// This should rarely be needed by classes. | ||
| 303 | /// | ||
| 304 | /// # Arguments | ||
| 305 | /// | 309 | /// |
| 306 | /// * `max_packet_size` - Maximum packet size in bytes. Must be one of 8, 16, 32 or 64. | 310 | /// Alternate setting numbers are guaranteed to be allocated consecutively, starting from 0. |
| 307 | /// | 311 | /// |
| 308 | /// # Panics | 312 | /// The first alternate setting, with number 0, is the default one. |
| 309 | /// | 313 | pub fn alt_setting( |
| 310 | /// Panics if endpoint allocation fails, because running out of endpoints or memory is not | 314 | &mut self, |
| 311 | /// feasibly recoverable. | 315 | class: u8, |
| 312 | #[inline] | 316 | subclass: u8, |
| 313 | pub fn alloc_control_pipe(&mut self, max_packet_size: u16) -> D::ControlPipe { | 317 | protocol: u8, |
| 314 | self.driver | 318 | ) -> InterfaceAltBuilder<'_, 'd, D> { |
| 315 | .alloc_control_pipe(max_packet_size) | 319 | let number = self.next_alt_setting_number; |
| 316 | .expect("alloc_control_pipe failed") | 320 | self.next_alt_setting_number += 1; |
| 321 | |||
| 322 | self.builder.config_descriptor.interface_alt( | ||
| 323 | self.interface_number, | ||
| 324 | number, | ||
| 325 | class, | ||
| 326 | subclass, | ||
| 327 | protocol, | ||
| 328 | None, | ||
| 329 | ); | ||
| 330 | |||
| 331 | InterfaceAltBuilder { | ||
| 332 | builder: self.builder, | ||
| 333 | interface_number: self.interface_number, | ||
| 334 | alt_setting_number: number, | ||
| 335 | } | ||
| 317 | } | 336 | } |
| 337 | } | ||
| 318 | 338 | ||
| 319 | /// Allocates a bulk in endpoint. | 339 | /// Interface alternate setting builder. |
| 320 | /// | 340 | pub struct InterfaceAltBuilder<'a, 'd, D: Driver<'d>> { |
| 321 | /// # Arguments | 341 | builder: &'a mut Builder<'d, D>, |
| 322 | /// | 342 | interface_number: InterfaceNumber, |
| 323 | /// * `max_packet_size` - Maximum packet size in bytes. Must be one of 8, 16, 32 or 64. | 343 | alt_setting_number: u8, |
| 324 | /// | 344 | } |
| 325 | /// # Panics | 345 | |
| 326 | /// | 346 | impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> { |
| 327 | /// Panics if endpoint allocation fails, because running out of endpoints or memory is not | 347 | /// Get the interface number. |
| 328 | /// feasibly recoverable. | 348 | pub fn interface_number(&self) -> InterfaceNumber { |
| 329 | #[inline] | 349 | self.interface_number |
| 330 | pub fn alloc_bulk_endpoint_in(&mut self, max_packet_size: u16) -> D::EndpointIn { | ||
| 331 | self.alloc_endpoint_in(None, EndpointType::Bulk, max_packet_size, 0) | ||
| 332 | .expect("alloc_ep failed") | ||
| 333 | } | 350 | } |
| 334 | 351 | ||
| 335 | /// Allocates a bulk out endpoint. | 352 | /// Get the alternate setting number. |
| 336 | /// | 353 | pub fn alt_setting_number(&self) -> u8 { |
| 337 | /// # Arguments | 354 | self.alt_setting_number |
| 338 | /// | ||
| 339 | /// * `max_packet_size` - Maximum packet size in bytes. Must be one of 8, 16, 32 or 64. | ||
| 340 | /// | ||
| 341 | /// # Panics | ||
| 342 | /// | ||
| 343 | /// Panics if endpoint allocation fails, because running out of endpoints or memory is not | ||
| 344 | /// feasibly recoverable. | ||
| 345 | #[inline] | ||
| 346 | pub fn alloc_bulk_endpoint_out(&mut self, max_packet_size: u16) -> D::EndpointOut { | ||
| 347 | self.alloc_endpoint_out(None, EndpointType::Bulk, max_packet_size, 0) | ||
| 348 | .expect("alloc_ep failed") | ||
| 349 | } | 355 | } |
| 350 | 356 | ||
| 351 | /// Allocates a bulk in endpoint. | 357 | /// Add a custom descriptor to this alternate setting. |
| 352 | /// | ||
| 353 | /// # Arguments | ||
| 354 | /// | ||
| 355 | /// * `max_packet_size` - Maximum packet size in bytes. Cannot exceed 64 bytes. | ||
| 356 | /// | 358 | /// |
| 357 | /// # Panics | 359 | /// Descriptors are written in the order builder functions are called. Note that some |
| 358 | /// | 360 | /// classes care about the order. |
| 359 | /// Panics if endpoint allocation fails, because running out of endpoints or memory is not | 361 | pub fn descriptor(&mut self, descriptor_type: u8, descriptor: &[u8]) { |
| 360 | /// feasibly recoverable. | 362 | self.builder |
| 361 | #[inline] | 363 | .config_descriptor |
| 362 | pub fn alloc_interrupt_endpoint_in( | 364 | .write(descriptor_type, descriptor) |
| 365 | } | ||
| 366 | |||
| 367 | fn endpoint_in( | ||
| 363 | &mut self, | 368 | &mut self, |
| 369 | ep_addr: Option<EndpointAddress>, | ||
| 370 | ep_type: EndpointType, | ||
| 364 | max_packet_size: u16, | 371 | max_packet_size: u16, |
| 365 | interval: u8, | 372 | interval: u8, |
| 366 | ) -> D::EndpointIn { | 373 | ) -> D::EndpointIn { |
| 367 | self.alloc_endpoint_in(None, EndpointType::Interrupt, max_packet_size, interval) | 374 | let ep = self |
| 368 | .expect("alloc_ep failed") | 375 | .builder |
| 376 | .driver | ||
| 377 | .alloc_endpoint_in(ep_addr, ep_type, max_packet_size, interval) | ||
| 378 | .expect("alloc_endpoint_in failed"); | ||
| 379 | |||
| 380 | self.builder.config_descriptor.endpoint(ep.info()); | ||
| 381 | |||
| 382 | ep | ||
| 369 | } | 383 | } |
| 370 | 384 | ||
| 371 | /// Allocates a bulk in endpoint. | 385 | fn endpoint_out( |
| 372 | /// | ||
| 373 | /// # Arguments | ||
| 374 | /// | ||
| 375 | /// * `max_packet_size` - Maximum packet size in bytes. Cannot exceed 64 bytes. | ||
| 376 | /// | ||
| 377 | /// # Panics | ||
| 378 | /// | ||
| 379 | /// Panics if endpoint allocation fails, because running out of endpoints or memory is not | ||
| 380 | /// feasibly recoverable. | ||
| 381 | #[inline] | ||
| 382 | pub fn alloc_interrupt_endpoint_out( | ||
| 383 | &mut self, | 386 | &mut self, |
| 387 | ep_addr: Option<EndpointAddress>, | ||
| 388 | ep_type: EndpointType, | ||
| 384 | max_packet_size: u16, | 389 | max_packet_size: u16, |
| 385 | interval: u8, | 390 | interval: u8, |
| 386 | ) -> D::EndpointOut { | 391 | ) -> D::EndpointOut { |
| 387 | self.alloc_endpoint_out(None, EndpointType::Interrupt, max_packet_size, interval) | 392 | let ep = self |
| 388 | .expect("alloc_ep failed") | 393 | .builder |
| 394 | .driver | ||
| 395 | .alloc_endpoint_out(ep_addr, ep_type, max_packet_size, interval) | ||
| 396 | .expect("alloc_endpoint_out failed"); | ||
| 397 | |||
| 398 | self.builder.config_descriptor.endpoint(ep.info()); | ||
| 399 | |||
| 400 | ep | ||
| 401 | } | ||
| 402 | |||
| 403 | /// Allocate a BULK IN endpoint and write its descriptor. | ||
| 404 | /// | ||
| 405 | /// Descriptors are written in the order builder functions are called. Note that some | ||
| 406 | /// classes care about the order. | ||
| 407 | pub fn endpoint_bulk_in(&mut self, max_packet_size: u16) -> D::EndpointIn { | ||
| 408 | self.endpoint_in(None, EndpointType::Bulk, max_packet_size, 0) | ||
| 409 | } | ||
| 410 | |||
| 411 | /// Allocate a BULK OUT endpoint and write its descriptor. | ||
| 412 | /// | ||
| 413 | /// Descriptors are written in the order builder functions are called. Note that some | ||
| 414 | /// classes care about the order. | ||
| 415 | pub fn endpoint_bulk_out(&mut self, max_packet_size: u16) -> D::EndpointOut { | ||
| 416 | self.endpoint_out(None, EndpointType::Bulk, max_packet_size, 0) | ||
| 417 | } | ||
| 418 | |||
| 419 | /// Allocate a INTERRUPT IN endpoint and write its descriptor. | ||
| 420 | /// | ||
| 421 | /// Descriptors are written in the order builder functions are called. Note that some | ||
| 422 | /// classes care about the order. | ||
| 423 | pub fn endpoint_interrupt_in(&mut self, max_packet_size: u16, interval: u8) -> D::EndpointIn { | ||
| 424 | self.endpoint_in(None, EndpointType::Interrupt, max_packet_size, interval) | ||
| 425 | } | ||
| 426 | |||
| 427 | /// Allocate a INTERRUPT OUT endpoint and write its descriptor. | ||
| 428 | pub fn endpoint_interrupt_out(&mut self, max_packet_size: u16, interval: u8) -> D::EndpointOut { | ||
| 429 | self.endpoint_out(None, EndpointType::Interrupt, max_packet_size, interval) | ||
| 389 | } | 430 | } |
| 390 | } | 431 | } |
diff --git a/embassy-usb/src/descriptor.rs b/embassy-usb/src/descriptor.rs index ff971e127..b61dea4b4 100644 --- a/embassy-usb/src/descriptor.rs +++ b/embassy-usb/src/descriptor.rs | |||
| @@ -33,12 +33,11 @@ pub mod capability_type { | |||
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | /// A writer for USB descriptors. | 35 | /// A writer for USB descriptors. |
| 36 | pub struct DescriptorWriter<'a> { | 36 | pub(crate) struct DescriptorWriter<'a> { |
| 37 | buf: &'a mut [u8], | 37 | pub buf: &'a mut [u8], |
| 38 | position: usize, | 38 | position: usize, |
| 39 | num_interfaces_mark: Option<usize>, | 39 | num_interfaces_mark: Option<usize>, |
| 40 | num_endpoints_mark: Option<usize>, | 40 | num_endpoints_mark: Option<usize>, |
| 41 | write_iads: bool, | ||
| 42 | } | 41 | } |
| 43 | 42 | ||
| 44 | impl<'a> DescriptorWriter<'a> { | 43 | impl<'a> DescriptorWriter<'a> { |
| @@ -48,7 +47,6 @@ impl<'a> DescriptorWriter<'a> { | |||
| 48 | position: 0, | 47 | position: 0, |
| 49 | num_interfaces_mark: None, | 48 | num_interfaces_mark: None, |
| 50 | num_endpoints_mark: None, | 49 | num_endpoints_mark: None, |
| 51 | write_iads: false, | ||
| 52 | } | 50 | } |
| 53 | } | 51 | } |
| 54 | 52 | ||
| @@ -106,8 +104,6 @@ impl<'a> DescriptorWriter<'a> { | |||
| 106 | pub(crate) fn configuration(&mut self, config: &Config) { | 104 | pub(crate) fn configuration(&mut self, config: &Config) { |
| 107 | self.num_interfaces_mark = Some(self.position + 4); | 105 | self.num_interfaces_mark = Some(self.position + 4); |
| 108 | 106 | ||
| 109 | self.write_iads = config.composite_with_iads; | ||
| 110 | |||
| 111 | self.write( | 107 | self.write( |
| 112 | descriptor_type::CONFIGURATION, | 108 | descriptor_type::CONFIGURATION, |
| 113 | &[ | 109 | &[ |
| @@ -160,10 +156,6 @@ impl<'a> DescriptorWriter<'a> { | |||
| 160 | function_sub_class: u8, | 156 | function_sub_class: u8, |
| 161 | function_protocol: u8, | 157 | function_protocol: u8, |
| 162 | ) { | 158 | ) { |
| 163 | if !self.write_iads { | ||
| 164 | return; | ||
| 165 | } | ||
| 166 | |||
| 167 | self.write( | 159 | self.write( |
| 168 | descriptor_type::IAD, | 160 | descriptor_type::IAD, |
| 169 | &[ | 161 | &[ |
| @@ -177,33 +169,6 @@ impl<'a> DescriptorWriter<'a> { | |||
| 177 | ); | 169 | ); |
| 178 | } | 170 | } |
| 179 | 171 | ||
| 180 | /// Writes a interface descriptor. | ||
| 181 | /// | ||
| 182 | /// # Arguments | ||
| 183 | /// | ||
| 184 | /// * `number` - Interface number previously allocated with | ||
| 185 | /// [`UsbDeviceBuilder::interface`](crate::bus::UsbDeviceBuilder::interface). | ||
| 186 | /// * `interface_class` - Class code assigned by USB.org. Use `0xff` for vendor-specific devices | ||
| 187 | /// that do not conform to any class. | ||
| 188 | /// * `interface_sub_class` - Sub-class code. Depends on class. | ||
| 189 | /// * `interface_protocol` - Protocol code. Depends on class and sub-class. | ||
| 190 | pub fn interface( | ||
| 191 | &mut self, | ||
| 192 | number: InterfaceNumber, | ||
| 193 | interface_class: u8, | ||
| 194 | interface_sub_class: u8, | ||
| 195 | interface_protocol: u8, | ||
| 196 | ) { | ||
| 197 | self.interface_alt( | ||
| 198 | number, | ||
| 199 | DEFAULT_ALTERNATE_SETTING, | ||
| 200 | interface_class, | ||
| 201 | interface_sub_class, | ||
| 202 | interface_protocol, | ||
| 203 | None, | ||
| 204 | ) | ||
| 205 | } | ||
| 206 | |||
| 207 | /// Writes a interface descriptor with a specific alternate setting and | 172 | /// Writes a interface descriptor with a specific alternate setting and |
| 208 | /// interface string identifier. | 173 | /// interface string identifier. |
| 209 | /// | 174 | /// |
diff --git a/embassy-usb/src/lib.rs b/embassy-usb/src/lib.rs index baeca099f..7cd00fbaf 100644 --- a/embassy-usb/src/lib.rs +++ b/embassy-usb/src/lib.rs | |||
| @@ -19,8 +19,8 @@ use self::descriptor::*; | |||
| 19 | use self::driver::{Bus, Driver, Event}; | 19 | use self::driver::{Bus, Driver, Event}; |
| 20 | use self::types::*; | 20 | use self::types::*; |
| 21 | 21 | ||
| 22 | pub use self::builder::Builder; | ||
| 22 | pub use self::builder::Config; | 23 | pub use self::builder::Config; |
| 23 | pub use self::builder::UsbDeviceBuilder; | ||
| 24 | 24 | ||
| 25 | /// The global state of the USB device. | 25 | /// The global state of the USB device. |
| 26 | /// | 26 | /// |
diff --git a/examples/nrf/src/bin/usb_hid_keyboard.rs b/examples/nrf/src/bin/usb_hid_keyboard.rs index a2d78b08e..9fa7ab334 100644 --- a/examples/nrf/src/bin/usb_hid_keyboard.rs +++ b/examples/nrf/src/bin/usb_hid_keyboard.rs | |||
| @@ -17,7 +17,7 @@ use embassy_nrf::pac; | |||
| 17 | use embassy_nrf::usb::Driver; | 17 | use embassy_nrf::usb::Driver; |
| 18 | use embassy_nrf::Peripherals; | 18 | use embassy_nrf::Peripherals; |
| 19 | use embassy_usb::control::OutResponse; | 19 | use embassy_usb::control::OutResponse; |
| 20 | use embassy_usb::{Config, DeviceStateHandler, UsbDeviceBuilder}; | 20 | use embassy_usb::{Builder, Config, DeviceStateHandler}; |
| 21 | use embassy_usb_hid::{HidReaderWriter, ReportId, RequestHandler, State}; | 21 | use embassy_usb_hid::{HidReaderWriter, ReportId, RequestHandler, State}; |
| 22 | use futures::future::join; | 22 | use futures::future::join; |
| 23 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; | 23 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; |
| @@ -77,7 +77,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 77 | 77 | ||
| 78 | let mut state = State::new(); | 78 | let mut state = State::new(); |
| 79 | 79 | ||
| 80 | let mut builder = UsbDeviceBuilder::new( | 80 | let mut builder = Builder::new( |
| 81 | driver, | 81 | driver, |
| 82 | config, | 82 | config, |
| 83 | &mut device_descriptor, | 83 | &mut device_descriptor, |
diff --git a/examples/nrf/src/bin/usb_hid_mouse.rs b/examples/nrf/src/bin/usb_hid_mouse.rs index 1e98dd1ae..92aeffda2 100644 --- a/examples/nrf/src/bin/usb_hid_mouse.rs +++ b/examples/nrf/src/bin/usb_hid_mouse.rs | |||
| @@ -12,7 +12,7 @@ use embassy_nrf::pac; | |||
| 12 | use embassy_nrf::usb::Driver; | 12 | use embassy_nrf::usb::Driver; |
| 13 | use embassy_nrf::Peripherals; | 13 | use embassy_nrf::Peripherals; |
| 14 | use embassy_usb::control::OutResponse; | 14 | use embassy_usb::control::OutResponse; |
| 15 | use embassy_usb::{Config, UsbDeviceBuilder}; | 15 | use embassy_usb::{Builder, Config}; |
| 16 | use embassy_usb_hid::{HidWriter, ReportId, RequestHandler, State}; | 16 | use embassy_usb_hid::{HidWriter, ReportId, RequestHandler, State}; |
| 17 | use futures::future::join; | 17 | use futures::future::join; |
| 18 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; | 18 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; |
| @@ -54,7 +54,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 54 | 54 | ||
| 55 | let mut state = State::new(); | 55 | let mut state = State::new(); |
| 56 | 56 | ||
| 57 | let mut builder = UsbDeviceBuilder::new( | 57 | let mut builder = Builder::new( |
| 58 | driver, | 58 | driver, |
| 59 | config, | 59 | config, |
| 60 | &mut device_descriptor, | 60 | &mut device_descriptor, |
diff --git a/examples/nrf/src/bin/usb_serial.rs b/examples/nrf/src/bin/usb_serial.rs index 987cc4139..6081ee917 100644 --- a/examples/nrf/src/bin/usb_serial.rs +++ b/examples/nrf/src/bin/usb_serial.rs | |||
| @@ -11,7 +11,7 @@ use embassy_nrf::pac; | |||
| 11 | use embassy_nrf::usb::{Driver, Instance}; | 11 | use embassy_nrf::usb::{Driver, Instance}; |
| 12 | use embassy_nrf::Peripherals; | 12 | use embassy_nrf::Peripherals; |
| 13 | use embassy_usb::driver::EndpointError; | 13 | use embassy_usb::driver::EndpointError; |
| 14 | use embassy_usb::{Config, UsbDeviceBuilder}; | 14 | use embassy_usb::{Builder, Config}; |
| 15 | use embassy_usb_serial::{CdcAcmClass, State}; | 15 | use embassy_usb_serial::{CdcAcmClass, State}; |
| 16 | use futures::future::join; | 16 | use futures::future::join; |
| 17 | 17 | ||
| @@ -47,7 +47,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 47 | 47 | ||
| 48 | let mut state = State::new(); | 48 | let mut state = State::new(); |
| 49 | 49 | ||
| 50 | let mut builder = UsbDeviceBuilder::new( | 50 | let mut builder = Builder::new( |
| 51 | driver, | 51 | driver, |
| 52 | config, | 52 | config, |
| 53 | &mut device_descriptor, | 53 | &mut device_descriptor, |
diff --git a/examples/nrf/src/bin/usb_serial_multitask.rs b/examples/nrf/src/bin/usb_serial_multitask.rs index 5fcb0e052..d4b3000e7 100644 --- a/examples/nrf/src/bin/usb_serial_multitask.rs +++ b/examples/nrf/src/bin/usb_serial_multitask.rs | |||
| @@ -12,7 +12,7 @@ use embassy_nrf::usb::Driver; | |||
| 12 | use embassy_nrf::Peripherals; | 12 | use embassy_nrf::Peripherals; |
| 13 | use embassy_nrf::{interrupt, peripherals}; | 13 | use embassy_nrf::{interrupt, peripherals}; |
| 14 | use embassy_usb::driver::EndpointError; | 14 | use embassy_usb::driver::EndpointError; |
| 15 | use embassy_usb::{Config, UsbDevice, UsbDeviceBuilder}; | 15 | use embassy_usb::{Builder, Config, UsbDevice}; |
| 16 | use embassy_usb_serial::{CdcAcmClass, State}; | 16 | use embassy_usb_serial::{CdcAcmClass, State}; |
| 17 | 17 | ||
| 18 | use defmt_rtt as _; // global logger | 18 | use defmt_rtt as _; // global logger |
| @@ -72,7 +72,7 @@ async fn main(spawner: Spawner, p: Peripherals) { | |||
| 72 | }); | 72 | }); |
| 73 | 73 | ||
| 74 | // Create embassy-usb DeviceBuilder using the driver and config. | 74 | // Create embassy-usb DeviceBuilder using the driver and config. |
| 75 | let mut builder = UsbDeviceBuilder::new( | 75 | let mut builder = Builder::new( |
| 76 | driver, | 76 | driver, |
| 77 | config, | 77 | config, |
| 78 | &mut res.device_descriptor, | 78 | &mut res.device_descriptor, |
