aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xci.sh1
-rw-r--r--embassy-nrf/src/usb.rs94
-rw-r--r--embassy-rp/Cargo.toml2
-rw-r--r--embassy-rp/src/gpio.rs5
-rw-r--r--embassy-stm32/src/exti.rs2
-rw-r--r--embassy-stm32/src/gpio.rs11
-rw-r--r--embassy-stm32/src/rcc/f3.rs26
-rw-r--r--embassy-stm32/src/rcc/f7.rs2
-rw-r--r--embassy-stm32/src/rcc/mod.rs4
-rw-r--r--embassy-stm32/src/usart/mod.rs6
-rw-r--r--embassy-stm32/src/usb_otg.rs4
-rw-r--r--embassy-usb-ncm/src/lib.rs14
-rw-r--r--embassy-usb/src/builder.rs14
-rw-r--r--embassy-usb/src/control.rs150
-rw-r--r--embassy-usb/src/descriptor.rs1
-rw-r--r--embassy-usb/src/driver.rs21
-rw-r--r--embassy-usb/src/lib.rs335
-rw-r--r--examples/nrf/src/bin/usb_hid_keyboard.rs2
-rw-r--r--examples/nrf/src/bin/usb_hid_mouse.rs2
-rw-r--r--examples/nrf/src/bin/usb_serial.rs9
-rw-r--r--examples/nrf/src/bin/usb_serial_multitask.rs11
21 files changed, 317 insertions, 399 deletions
diff --git a/ci.sh b/ci.sh
index c6fe9c4aa..00dc8cb9c 100755
--- a/ci.sh
+++ b/ci.sh
@@ -58,6 +58,7 @@ cargo batch \
58 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features nightly,stm32l552ze,defmt,exti,time-driver-any,unstable-traits \ 58 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features nightly,stm32l552ze,defmt,exti,time-driver-any,unstable-traits \
59 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32wl54jc-cm0p,defmt,exti,time-driver-any,unstable-traits \ 59 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32wl54jc-cm0p,defmt,exti,time-driver-any,unstable-traits \
60 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32wle5ub,defmt,exti,time-driver-any,unstable-traits \ 60 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32wle5ub,defmt,exti,time-driver-any,unstable-traits \
61 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7m-none-eabi --features nightly,stm32f107vc,defmt,exti,time-driver-any,unstable-traits \
61 --- build --release --manifest-path embassy-boot/nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840 \ 62 --- build --release --manifest-path embassy-boot/nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840 \
62 --- build --release --manifest-path embassy-boot/stm32/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32wl55jc-cm4 \ 63 --- build --release --manifest-path embassy-boot/stm32/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32wl55jc-cm4 \
63 --- build --release --manifest-path docs/modules/ROOT/examples/basic/Cargo.toml --target thumbv7em-none-eabi \ 64 --- build --release --manifest-path docs/modules/ROOT/examples/basic/Cargo.toml --target thumbv7em-none-eabi \
diff --git a/embassy-nrf/src/usb.rs b/embassy-nrf/src/usb.rs
index c032b2cc5..1162946a9 100644
--- a/embassy-nrf/src/usb.rs
+++ b/embassy-nrf/src/usb.rs
@@ -143,58 +143,46 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
143 143
144 fn alloc_endpoint_in( 144 fn alloc_endpoint_in(
145 &mut self, 145 &mut self,
146 ep_addr: Option<EndpointAddress>,
147 ep_type: EndpointType, 146 ep_type: EndpointType,
148 max_packet_size: u16, 147 packet_size: u16,
149 interval: u8, 148 interval: u8,
150 ) -> Result<Self::EndpointIn, driver::EndpointAllocError> { 149 ) -> Result<Self::EndpointIn, driver::EndpointAllocError> {
151 let index = self 150 let index = self.alloc_in.allocate(ep_type)?;
152 .alloc_in
153 .allocate(ep_addr, ep_type, max_packet_size, interval)?;
154 let ep_addr = EndpointAddress::from_parts(index, UsbDirection::In); 151 let ep_addr = EndpointAddress::from_parts(index, UsbDirection::In);
155 Ok(Endpoint::new(EndpointInfo { 152 Ok(Endpoint::new(EndpointInfo {
156 addr: ep_addr, 153 addr: ep_addr,
157 ep_type, 154 ep_type,
158 max_packet_size, 155 max_packet_size: packet_size,
159 interval, 156 interval,
160 })) 157 }))
161 } 158 }
162 159
163 fn alloc_endpoint_out( 160 fn alloc_endpoint_out(
164 &mut self, 161 &mut self,
165 ep_addr: Option<EndpointAddress>,
166 ep_type: EndpointType, 162 ep_type: EndpointType,
167 max_packet_size: u16, 163 packet_size: u16,
168 interval: u8, 164 interval: u8,
169 ) -> Result<Self::EndpointOut, driver::EndpointAllocError> { 165 ) -> Result<Self::EndpointOut, driver::EndpointAllocError> {
170 let index = self 166 let index = self.alloc_out.allocate(ep_type)?;
171 .alloc_out
172 .allocate(ep_addr, ep_type, max_packet_size, interval)?;
173 let ep_addr = EndpointAddress::from_parts(index, UsbDirection::Out); 167 let ep_addr = EndpointAddress::from_parts(index, UsbDirection::Out);
174 Ok(Endpoint::new(EndpointInfo { 168 Ok(Endpoint::new(EndpointInfo {
175 addr: ep_addr, 169 addr: ep_addr,
176 ep_type, 170 ep_type,
177 max_packet_size, 171 max_packet_size: packet_size,
178 interval, 172 interval,
179 })) 173 }))
180 } 174 }
181 175
182 fn alloc_control_pipe( 176 fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
183 &mut self, 177 (
184 max_packet_size: u16, 178 Bus {
185 ) -> Result<Self::ControlPipe, driver::EndpointAllocError> { 179 phantom: PhantomData,
186 self.alloc_endpoint_out(Some(0x00.into()), EndpointType::Control, max_packet_size, 0)?; 180 },
187 self.alloc_endpoint_in(Some(0x80.into()), EndpointType::Control, max_packet_size, 0)?; 181 ControlPipe {
188 Ok(ControlPipe { 182 _phantom: PhantomData,
189 _phantom: PhantomData, 183 max_packet_size: control_max_packet_size,
190 max_packet_size, 184 },
191 }) 185 )
192 }
193
194 fn into_bus(self) -> Self::Bus {
195 Bus {
196 phantom: PhantomData,
197 }
198 } 186 }
199} 187}
200 188
@@ -681,8 +669,7 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
681 .await; 669 .await;
682 670
683 // Reset shorts 671 // Reset shorts
684 regs.shorts 672 regs.shorts.write(|w| w);
685 .modify(|_, w| w.ep0datadone_ep0status().clear_bit());
686 regs.events_ep0setup.reset(); 673 regs.events_ep0setup.reset();
687 674
688 let mut buf = [0; 8]; 675 let mut buf = [0; 8];
@@ -746,7 +733,7 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
746 } 733 }
747 734
748 regs.shorts 735 regs.shorts
749 .modify(|_, w| w.ep0datadone_ep0status().bit(last_packet)); 736 .write(|w| w.ep0datadone_ep0status().bit(last_packet));
750 737
751 regs.intenset.write(|w| { 738 regs.intenset.write(|w| {
752 w.usbreset().set(); 739 w.usbreset().set();
@@ -796,25 +783,14 @@ fn dma_end() {
796 783
797struct Allocator { 784struct Allocator {
798 used: u16, 785 used: u16,
799 // Buffers can be up to 64 Bytes since this is a Full-Speed implementation.
800 lens: [u8; 9],
801} 786}
802 787
803impl Allocator { 788impl Allocator {
804 fn new() -> Self { 789 fn new() -> Self {
805 Self { 790 Self { used: 0 }
806 used: 0,
807 lens: [0; 9],
808 }
809 } 791 }
810 792
811 fn allocate( 793 fn allocate(&mut self, ep_type: EndpointType) -> Result<usize, driver::EndpointAllocError> {
812 &mut self,
813 ep_addr: Option<EndpointAddress>,
814 ep_type: EndpointType,
815 max_packet_size: u16,
816 _interval: u8,
817 ) -> Result<usize, driver::EndpointAllocError> {
818 // Endpoint addresses are fixed in hardware: 794 // Endpoint addresses are fixed in hardware:
819 // - 0x80 / 0x00 - Control EP0 795 // - 0x80 / 0x00 - Control EP0
820 // - 0x81 / 0x01 - Bulk/Interrupt EP1 796 // - 0x81 / 0x01 - Bulk/Interrupt EP1
@@ -828,27 +804,16 @@ impl Allocator {
828 804
829 // Endpoint directions are allocated individually. 805 // Endpoint directions are allocated individually.
830 806
831 let alloc_index = if let Some(ep_addr) = ep_addr { 807 let alloc_index = match ep_type {
832 match (ep_addr.index(), ep_type) { 808 EndpointType::Isochronous => 8,
833 (0, EndpointType::Control) => {} 809 EndpointType::Control => return Err(driver::EndpointAllocError),
834 (8, EndpointType::Isochronous) => {} 810 EndpointType::Interrupt | EndpointType::Bulk => {
835 (n, EndpointType::Bulk) | (n, EndpointType::Interrupt) if n >= 1 && n <= 7 => {} 811 // Find rightmost zero bit in 1..=7
836 _ => return Err(driver::EndpointAllocError), 812 let ones = (self.used >> 1).trailing_ones() as usize;
837 } 813 if ones >= 7 {
838 814 return Err(driver::EndpointAllocError);
839 ep_addr.index()
840 } else {
841 match ep_type {
842 EndpointType::Isochronous => 8,
843 EndpointType::Control => 0,
844 EndpointType::Interrupt | EndpointType::Bulk => {
845 // Find rightmost zero bit in 1..=7
846 let ones = (self.used >> 1).trailing_ones() as usize;
847 if ones >= 7 {
848 return Err(driver::EndpointAllocError);
849 }
850 ones + 1
851 } 815 }
816 ones + 1
852 } 817 }
853 }; 818 };
854 819
@@ -857,7 +822,6 @@ impl Allocator {
857 } 822 }
858 823
859 self.used |= 1 << alloc_index; 824 self.used |= 1 << alloc_index;
860 self.lens[alloc_index] = max_packet_size as u8;
861 825
862 Ok(alloc_index) 826 Ok(alloc_index)
863 } 827 }
diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml
index 17fce54e5..9f295c759 100644
--- a/embassy-rp/Cargo.toml
+++ b/embassy-rp/Cargo.toml
@@ -15,7 +15,7 @@ flavors = [
15[features] 15[features]
16 16
17# Reexport the PAC for the currently enabled chip at `embassy_rp::pac`. 17# Reexport the PAC for the currently enabled chip at `embassy_rp::pac`.
18# This is unstable because semver-minor (non-breaking) releases of embassy-nrf may major-bump (breaking) the PAC version. 18# This is unstable because semver-minor (non-breaking) releases of embassy-rp may major-bump (breaking) the PAC version.
19# If this is an issue for you, you're encouraged to directly depend on a fixed version of the PAC. 19# If this is an issue for you, you're encouraged to directly depend on a fixed version of the PAC.
20# There are no plans to make this stable. 20# There are no plans to make this stable.
21unstable-pac = [] 21unstable-pac = []
diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs
index 598759036..28dfce476 100644
--- a/embassy-rp/src/gpio.rs
+++ b/embassy-rp/src/gpio.rs
@@ -127,8 +127,9 @@ impl<'d, T: Pin> Output<'d, T> {
127 127
128 /// Is the output pin set as low? 128 /// Is the output pin set as low?
129 pub fn is_set_low(&self) -> bool { 129 pub fn is_set_low(&self) -> bool {
130 // todo 130 // Reading from SIO: GPIO_OUT gives the last value written.
131 true 131 let val = 1 << self.pin.pin();
132 unsafe { (self.pin.sio_out().value().read() & val) == 0 }
132 } 133 }
133} 134}
134 135
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs
index 957a1ca55..d065a5557 100644
--- a/embassy-stm32/src/exti.rs
+++ b/embassy-stm32/src/exti.rs
@@ -371,7 +371,7 @@ pub(crate) unsafe fn init() {
371 371
372 foreach_exti_irq!(enable_irq); 372 foreach_exti_irq!(enable_irq);
373 373
374 #[cfg(not(any(rcc_wb, rcc_wl5, rcc_wle, rcc_f1)))] 374 #[cfg(not(any(rcc_wb, rcc_wl5, rcc_wle, stm32f1)))]
375 <crate::peripherals::SYSCFG as crate::rcc::sealed::RccPeripheral>::enable(); 375 <crate::peripherals::SYSCFG as crate::rcc::sealed::RccPeripheral>::enable();
376 #[cfg(stm32f1)] 376 #[cfg(stm32f1)]
377 <crate::peripherals::AFIO as crate::rcc::sealed::RccPeripheral>::enable(); 377 <crate::peripherals::AFIO as crate::rcc::sealed::RccPeripheral>::enable();
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs
index 30f900316..b6982e91a 100644
--- a/embassy-stm32/src/gpio.rs
+++ b/embassy-stm32/src/gpio.rs
@@ -511,10 +511,19 @@ pub(crate) mod sealed {
511 self.set_as_analog(); 511 self.set_as_analog();
512 } 512 }
513 513
514 #[cfg(gpio_v2)]
515 #[inline] 514 #[inline]
516 unsafe fn set_speed(&self, speed: Speed) { 515 unsafe fn set_speed(&self, speed: Speed) {
517 let pin = self._pin() as usize; 516 let pin = self._pin() as usize;
517
518 #[cfg(gpio_v1)]
519 {
520 let crlh = if pin < 8 { 0 } else { 1 };
521 self.block().cr(crlh).modify(|w| {
522 w.set_mode(pin % 8, speed.into());
523 });
524 }
525
526 #[cfg(gpio_v2)]
518 self.block() 527 self.block()
519 .ospeedr() 528 .ospeedr()
520 .modify(|w| w.set_ospeedr(pin, speed.into())); 529 .modify(|w| w.set_ospeedr(pin, speed.into()));
diff --git a/embassy-stm32/src/rcc/f3.rs b/embassy-stm32/src/rcc/f3.rs
index ababc4f90..c2aec04c4 100644
--- a/embassy-stm32/src/rcc/f3.rs
+++ b/embassy-stm32/src/rcc/f3.rs
@@ -93,7 +93,10 @@ pub(crate) unsafe fn init(config: Config) {
93 assert!(pclk2 <= 72_000_000); 93 assert!(pclk2 <= 72_000_000);
94 94
95 // Set latency based on HCLK frquency 95 // Set latency based on HCLK frquency
96 FLASH.acr().write(|w| { 96 // RM0316: "The prefetch buffer must be kept on when using a prescaler
97 // different from 1 on the AHB clock.", "Half-cycle access cannot be
98 // used when there is a prescaler different from 1 on the AHB clock"
99 FLASH.acr().modify(|w| {
97 w.set_latency(if hclk <= 24_000_000 { 100 w.set_latency(if hclk <= 24_000_000 {
98 Latency::WS0 101 Latency::WS0
99 } else if hclk <= 48_000_000 { 102 } else if hclk <= 48_000_000 {
@@ -101,11 +104,16 @@ pub(crate) unsafe fn init(config: Config) {
101 } else { 104 } else {
102 Latency::WS2 105 Latency::WS2
103 }); 106 });
107 if hpre_div != 1 {
108 w.set_hlfcya(false);
109 w.set_prftbe(true);
110 }
104 }); 111 });
105 112
106 // Enable HSE 113 // Enable HSE
114 // RM0316: "Bits 31:26 Reserved, must be kept at reset value."
107 if config.hse.is_some() { 115 if config.hse.is_some() {
108 RCC.cr().write(|w| { 116 RCC.cr().modify(|w| {
109 w.set_hsebyp(config.bypass_hse); 117 w.set_hsebyp(config.bypass_hse);
110 // We turn on clock security to switch to HSI when HSE fails 118 // We turn on clock security to switch to HSI when HSE fails
111 w.set_csson(true); 119 w.set_csson(true);
@@ -115,27 +123,30 @@ pub(crate) unsafe fn init(config: Config) {
115 } 123 }
116 124
117 // Enable PLL 125 // Enable PLL
126 // RM0316: "Reserved, must be kept at reset value."
118 if let Some(ref pll_config) = pll_config { 127 if let Some(ref pll_config) = pll_config {
119 RCC.cfgr().write(|w| { 128 RCC.cfgr().modify(|w| {
120 w.set_pllmul(pll_config.pll_mul); 129 w.set_pllmul(pll_config.pll_mul);
121 w.set_pllsrc(pll_config.pll_src); 130 w.set_pllsrc(pll_config.pll_src);
122 }); 131 });
123 if let Some(pll_div) = pll_config.pll_div { 132 if let Some(pll_div) = pll_config.pll_div {
124 RCC.cfgr2().write(|w| w.set_prediv(pll_div)); 133 RCC.cfgr2().modify(|w| w.set_prediv(pll_div));
125 } 134 }
126 RCC.cr().modify(|w| w.set_pllon(true)); 135 RCC.cr().modify(|w| w.set_pllon(true));
127 while !RCC.cr().read().pllrdy() {} 136 while !RCC.cr().read().pllrdy() {}
128 } 137 }
129 138
139 // CFGR has been written before (PLL) don't overwrite these settings
130 if config.pll48 { 140 if config.pll48 {
131 let usb_pre = get_usb_pre(&config, sysclk, pclk1, &pll_config); 141 let usb_pre = get_usb_pre(&config, sysclk, pclk1, &pll_config);
132 RCC.cfgr().write(|w| { 142 RCC.cfgr().modify(|w| {
133 w.set_usbpre(usb_pre); 143 w.set_usbpre(usb_pre);
134 }); 144 });
135 } 145 }
136 146
137 // Set prescalers 147 // Set prescalers
138 RCC.cfgr().write(|w| { 148 // CFGR has been written before (PLL, PLL48) don't overwrite these settings
149 RCC.cfgr().modify(|w| {
139 w.set_ppre2(ppre2_bits); 150 w.set_ppre2(ppre2_bits);
140 w.set_ppre1(ppre1_bits); 151 w.set_ppre1(ppre1_bits);
141 w.set_hpre(hpre_bits); 152 w.set_hpre(hpre_bits);
@@ -146,7 +157,8 @@ pub(crate) unsafe fn init(config: Config) {
146 // 1 to 16 AHB cycles after write" 157 // 1 to 16 AHB cycles after write"
147 cortex_m::asm::delay(16); 158 cortex_m::asm::delay(16);
148 159
149 RCC.cfgr().write(|w| { 160 // CFGR has been written before (PLL, PLL48, clock divider) don't overwrite these settings
161 RCC.cfgr().modify(|w| {
150 w.set_sw(match (pll_config, config.hse) { 162 w.set_sw(match (pll_config, config.hse) {
151 (Some(_), _) => Sw::PLL, 163 (Some(_), _) => Sw::PLL,
152 (None, Some(_)) => Sw::HSE, 164 (None, Some(_)) => Sw::HSE,
diff --git a/embassy-stm32/src/rcc/f7.rs b/embassy-stm32/src/rcc/f7.rs
index 9f2c63c16..f45a725ce 100644
--- a/embassy-stm32/src/rcc/f7.rs
+++ b/embassy-stm32/src/rcc/f7.rs
@@ -170,7 +170,7 @@ pub(crate) unsafe fn init(config: Config) {
170 // Calculate real AHB clock 170 // Calculate real AHB clock
171 let hclk = sysclk / hpre_div; 171 let hclk = sysclk / hpre_div;
172 172
173 assert!(hclk < max::HCLK_MAX); 173 assert!(hclk <= max::HCLK_MAX);
174 174
175 let pclk1 = config 175 let pclk1 = config
176 .pclk1 176 .pclk1
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index d3710b8c3..959e59265 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -4,7 +4,7 @@ use crate::time::Hertz;
4use core::mem::MaybeUninit; 4use core::mem::MaybeUninit;
5 5
6#[cfg_attr(rcc_f0, path = "f0.rs")] 6#[cfg_attr(rcc_f0, path = "f0.rs")]
7#[cfg_attr(rcc_f1, path = "f1.rs")] 7#[cfg_attr(any(rcc_f1, rcc_f1cl), path = "f1.rs")]
8#[cfg_attr(rcc_f2, path = "f2.rs")] 8#[cfg_attr(rcc_f2, path = "f2.rs")]
9#[cfg_attr(rcc_f3, path = "f3.rs")] 9#[cfg_attr(rcc_f3, path = "f3.rs")]
10#[cfg_attr(any(rcc_f4, rcc_f410), path = "f4.rs")] 10#[cfg_attr(any(rcc_f4, rcc_f410), path = "f4.rs")]
@@ -56,7 +56,7 @@ pub struct Clocks {
56 #[cfg(any(rcc_f2, rcc_f4, rcc_f410, rcc_f7))] 56 #[cfg(any(rcc_f2, rcc_f4, rcc_f410, rcc_f7))]
57 pub pll48: Option<Hertz>, 57 pub pll48: Option<Hertz>,
58 58
59 #[cfg(rcc_f1)] 59 #[cfg(stm32f1)]
60 pub adc: Hertz, 60 pub adc: Hertz,
61 61
62 #[cfg(any(rcc_h7, rcc_h7ab))] 62 #[cfg(any(rcc_h7, rcc_h7ab))]
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index 6feecd184..472680113 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -219,7 +219,11 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
219 w.set_ue(true); 219 w.set_ue(true);
220 w.set_te(true); 220 w.set_te(true);
221 w.set_re(true); 221 w.set_re(true);
222 w.set_m0(vals::M0::BIT8); 222 w.set_m0(if config.parity != Parity::ParityNone {
223 vals::M0::BIT9
224 } else {
225 vals::M0::BIT8
226 });
223 w.set_pce(config.parity != Parity::ParityNone); 227 w.set_pce(config.parity != Parity::ParityNone);
224 w.set_ps(match config.parity { 228 w.set_ps(match config.parity {
225 Parity::ParityOdd => vals::Ps::ODD, 229 Parity::ParityOdd => vals::Ps::ODD,
diff --git a/embassy-stm32/src/usb_otg.rs b/embassy-stm32/src/usb_otg.rs
index 21b890d7c..c3cd776ca 100644
--- a/embassy-stm32/src/usb_otg.rs
+++ b/embassy-stm32/src/usb_otg.rs
@@ -3,7 +3,6 @@ use embassy::util::Unborrow;
3use embassy_hal_common::unborrow; 3use embassy_hal_common::unborrow;
4 4
5use crate::gpio::sealed::AFType; 5use crate::gpio::sealed::AFType;
6use crate::gpio::Speed;
7use crate::{peripherals, rcc::RccPeripheral}; 6use crate::{peripherals, rcc::RccPeripheral};
8 7
9macro_rules! config_ulpi_pins { 8macro_rules! config_ulpi_pins {
@@ -13,7 +12,8 @@ macro_rules! config_ulpi_pins {
13 critical_section::with(|_| unsafe { 12 critical_section::with(|_| unsafe {
14 $( 13 $(
15 $pin.set_as_af($pin.af_num(), AFType::OutputPushPull); 14 $pin.set_as_af($pin.af_num(), AFType::OutputPushPull);
16 $pin.set_speed(Speed::VeryHigh); 15 #[cfg(gpio_v2)]
16 $pin.set_speed(crate::gpio::Speed::VeryHigh);
17 )* 17 )*
18 }) 18 })
19 }; 19 };
diff --git a/embassy-usb-ncm/src/lib.rs b/embassy-usb-ncm/src/lib.rs
index 3a5abee8d..71d0691d4 100644
--- a/embassy-usb-ncm/src/lib.rs
+++ b/embassy-usb-ncm/src/lib.rs
@@ -133,6 +133,7 @@ impl Default for ControlShared {
133struct CommControl<'a> { 133struct CommControl<'a> {
134 mac_addr_string: StringIndex, 134 mac_addr_string: StringIndex,
135 shared: &'a ControlShared, 135 shared: &'a ControlShared,
136 mac_addr_str: [u8; 12],
136} 137}
137 138
138impl<'d> ControlHandler for CommControl<'d> { 139impl<'d> ControlHandler for CommControl<'d> {
@@ -178,24 +179,20 @@ impl<'d> ControlHandler for CommControl<'d> {
178 } 179 }
179 } 180 }
180 181
181 fn get_string<'a>( 182 fn get_string(&mut self, index: StringIndex, _lang_id: u16) -> Option<&str> {
182 &'a mut self,
183 index: StringIndex,
184 _lang_id: u16,
185 buf: &'a mut [u8],
186 ) -> Option<&'a str> {
187 if index == self.mac_addr_string { 183 if index == self.mac_addr_string {
188 let mac_addr = self.shared.mac_addr.get(); 184 let mac_addr = self.shared.mac_addr.get();
185 let s = &mut self.mac_addr_str;
189 for i in 0..12 { 186 for i in 0..12 {
190 let n = (mac_addr[i / 2] >> ((1 - i % 2) * 4)) & 0xF; 187 let n = (mac_addr[i / 2] >> ((1 - i % 2) * 4)) & 0xF;
191 buf[i] = match n { 188 s[i] = match n {
192 0x0..=0x9 => b'0' + n, 189 0x0..=0x9 => b'0' + n,
193 0xA..=0xF => b'A' + n - 0xA, 190 0xA..=0xF => b'A' + n - 0xA,
194 _ => unreachable!(), 191 _ => unreachable!(),
195 } 192 }
196 } 193 }
197 194
198 Some(unsafe { core::str::from_utf8_unchecked(&buf[..12]) }) 195 Some(unsafe { core::str::from_utf8_unchecked(s) })
199 } else { 196 } else {
200 warn!("unknown string index requested"); 197 warn!("unknown string index requested");
201 None 198 None
@@ -244,6 +241,7 @@ impl<'d, D: Driver<'d>> CdcNcmClass<'d, D> {
244 iface.handler(state.comm_control.write(CommControl { 241 iface.handler(state.comm_control.write(CommControl {
245 mac_addr_string, 242 mac_addr_string,
246 shared: &control_shared, 243 shared: &control_shared,
244 mac_addr_str: [0; 12],
247 })); 245 }));
248 let comm_if = iface.interface_number(); 246 let comm_if = iface.interface_number();
249 let mut alt = iface.alt_setting(USB_CLASS_CDC, CDC_SUBCLASS_NCM, CDC_PROTOCOL_NONE); 247 let mut alt = iface.alt_setting(USB_CLASS_CDC, CDC_SUBCLASS_NCM, CDC_PROTOCOL_NONE);
diff --git a/embassy-usb/src/builder.rs b/embassy-usb/src/builder.rs
index 8cf9c82a9..698a5f765 100644
--- a/embassy-usb/src/builder.rs
+++ b/embassy-usb/src/builder.rs
@@ -372,7 +372,6 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
372 372
373 fn endpoint_in( 373 fn endpoint_in(
374 &mut self, 374 &mut self,
375 ep_addr: Option<EndpointAddress>,
376 ep_type: EndpointType, 375 ep_type: EndpointType,
377 max_packet_size: u16, 376 max_packet_size: u16,
378 interval: u8, 377 interval: u8,
@@ -380,7 +379,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
380 let ep = self 379 let ep = self
381 .builder 380 .builder
382 .driver 381 .driver
383 .alloc_endpoint_in(ep_addr, ep_type, max_packet_size, interval) 382 .alloc_endpoint_in(ep_type, max_packet_size, interval)
384 .expect("alloc_endpoint_in failed"); 383 .expect("alloc_endpoint_in failed");
385 384
386 self.builder.config_descriptor.endpoint(ep.info()); 385 self.builder.config_descriptor.endpoint(ep.info());
@@ -390,7 +389,6 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
390 389
391 fn endpoint_out( 390 fn endpoint_out(
392 &mut self, 391 &mut self,
393 ep_addr: Option<EndpointAddress>,
394 ep_type: EndpointType, 392 ep_type: EndpointType,
395 max_packet_size: u16, 393 max_packet_size: u16,
396 interval: u8, 394 interval: u8,
@@ -398,7 +396,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
398 let ep = self 396 let ep = self
399 .builder 397 .builder
400 .driver 398 .driver
401 .alloc_endpoint_out(ep_addr, ep_type, max_packet_size, interval) 399 .alloc_endpoint_out(ep_type, max_packet_size, interval)
402 .expect("alloc_endpoint_out failed"); 400 .expect("alloc_endpoint_out failed");
403 401
404 self.builder.config_descriptor.endpoint(ep.info()); 402 self.builder.config_descriptor.endpoint(ep.info());
@@ -411,7 +409,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
411 /// Descriptors are written in the order builder functions are called. Note that some 409 /// Descriptors are written in the order builder functions are called. Note that some
412 /// classes care about the order. 410 /// classes care about the order.
413 pub fn endpoint_bulk_in(&mut self, max_packet_size: u16) -> D::EndpointIn { 411 pub fn endpoint_bulk_in(&mut self, max_packet_size: u16) -> D::EndpointIn {
414 self.endpoint_in(None, EndpointType::Bulk, max_packet_size, 0) 412 self.endpoint_in(EndpointType::Bulk, max_packet_size, 0)
415 } 413 }
416 414
417 /// Allocate a BULK OUT endpoint and write its descriptor. 415 /// Allocate a BULK OUT endpoint and write its descriptor.
@@ -419,7 +417,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
419 /// Descriptors are written in the order builder functions are called. Note that some 417 /// Descriptors are written in the order builder functions are called. Note that some
420 /// classes care about the order. 418 /// classes care about the order.
421 pub fn endpoint_bulk_out(&mut self, max_packet_size: u16) -> D::EndpointOut { 419 pub fn endpoint_bulk_out(&mut self, max_packet_size: u16) -> D::EndpointOut {
422 self.endpoint_out(None, EndpointType::Bulk, max_packet_size, 0) 420 self.endpoint_out(EndpointType::Bulk, max_packet_size, 0)
423 } 421 }
424 422
425 /// Allocate a INTERRUPT IN endpoint and write its descriptor. 423 /// Allocate a INTERRUPT IN endpoint and write its descriptor.
@@ -427,11 +425,11 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
427 /// Descriptors are written in the order builder functions are called. Note that some 425 /// Descriptors are written in the order builder functions are called. Note that some
428 /// classes care about the order. 426 /// classes care about the order.
429 pub fn endpoint_interrupt_in(&mut self, max_packet_size: u16, interval: u8) -> D::EndpointIn { 427 pub fn endpoint_interrupt_in(&mut self, max_packet_size: u16, interval: u8) -> D::EndpointIn {
430 self.endpoint_in(None, EndpointType::Interrupt, max_packet_size, interval) 428 self.endpoint_in(EndpointType::Interrupt, max_packet_size, interval)
431 } 429 }
432 430
433 /// Allocate a INTERRUPT OUT endpoint and write its descriptor. 431 /// Allocate a INTERRUPT OUT endpoint and write its descriptor.
434 pub fn endpoint_interrupt_out(&mut self, max_packet_size: u16, interval: u8) -> D::EndpointOut { 432 pub fn endpoint_interrupt_out(&mut self, max_packet_size: u16, interval: u8) -> D::EndpointOut {
435 self.endpoint_out(None, EndpointType::Interrupt, max_packet_size, interval) 433 self.endpoint_out(EndpointType::Interrupt, max_packet_size, interval)
436 } 434 }
437} 435}
diff --git a/embassy-usb/src/control.rs b/embassy-usb/src/control.rs
index ff42f9d78..12e5303c3 100644
--- a/embassy-usb/src/control.rs
+++ b/embassy-usb/src/control.rs
@@ -1,8 +1,5 @@
1use core::mem; 1use core::mem;
2 2
3use crate::descriptor::DescriptorWriter;
4use crate::driver::{self, EndpointError};
5
6use super::types::*; 3use super::types::*;
7 4
8/// Control request type. 5/// Control request type.
@@ -191,151 +188,8 @@ pub trait ControlHandler {
191 } 188 }
192 189
193 /// Called when a GET_DESCRIPTOR STRING control request is received. 190 /// Called when a GET_DESCRIPTOR STRING control request is received.
194 /// 191 fn get_string(&mut self, index: StringIndex, lang_id: u16) -> Option<&str> {
195 /// Write the response string somewhere (usually to `buf`, but you may use another buffer 192 let _ = (index, lang_id);
196 /// owned by yourself, or a static buffer), then return it.
197 fn get_string<'a>(
198 &'a mut self,
199 index: StringIndex,
200 lang_id: u16,
201 buf: &'a mut [u8],
202 ) -> Option<&'a str> {
203 let _ = (index, lang_id, buf);
204 None 193 None
205 } 194 }
206} 195}
207
208/// Typestate representing a ControlPipe in the DATA IN stage
209#[derive(Debug)]
210#[cfg_attr(feature = "defmt", derive(defmt::Format))]
211pub(crate) struct DataInStage {
212 pub(crate) length: usize,
213}
214
215/// Typestate representing a ControlPipe in the DATA OUT stage
216#[derive(Debug)]
217#[cfg_attr(feature = "defmt", derive(defmt::Format))]
218pub(crate) struct DataOutStage {
219 length: usize,
220}
221
222/// Typestate representing a ControlPipe in the STATUS stage
223#[derive(Debug)]
224#[cfg_attr(feature = "defmt", derive(defmt::Format))]
225pub(crate) struct StatusStage {}
226
227#[derive(Debug)]
228#[cfg_attr(feature = "defmt", derive(defmt::Format))]
229pub(crate) enum Setup {
230 DataIn(Request, DataInStage),
231 DataOut(Request, DataOutStage),
232}
233
234pub(crate) struct ControlPipe<C: driver::ControlPipe> {
235 control: C,
236}
237
238impl<C: driver::ControlPipe> ControlPipe<C> {
239 pub(crate) fn new(control: C) -> Self {
240 ControlPipe { control }
241 }
242
243 pub(crate) async fn setup(&mut self) -> Setup {
244 let req = self.control.setup().await;
245 trace!("control request: {:02x}", req);
246
247 match (req.direction, req.length) {
248 (UsbDirection::Out, n) => Setup::DataOut(
249 req,
250 DataOutStage {
251 length: usize::from(n),
252 },
253 ),
254 (UsbDirection::In, n) => Setup::DataIn(
255 req,
256 DataInStage {
257 length: usize::from(n),
258 },
259 ),
260 }
261 }
262
263 pub(crate) async fn data_out<'a>(
264 &mut self,
265 buf: &'a mut [u8],
266 stage: DataOutStage,
267 ) -> Result<(&'a [u8], StatusStage), EndpointError> {
268 if stage.length == 0 {
269 Ok((&[], StatusStage {}))
270 } else {
271 let req_length = stage.length;
272 let max_packet_size = self.control.max_packet_size();
273 let mut total = 0;
274
275 for chunk in buf.chunks_mut(max_packet_size) {
276 let size = self.control.data_out(chunk).await?;
277 total += size;
278 if size < max_packet_size || total == req_length {
279 break;
280 }
281 }
282
283 let res = &buf[0..total];
284 #[cfg(feature = "defmt")]
285 trace!(" control out data: {:02x}", res);
286 #[cfg(not(feature = "defmt"))]
287 trace!(" control out data: {:02x?}", res);
288
289 Ok((res, StatusStage {}))
290 }
291 }
292
293 pub(crate) async fn accept_in(&mut self, buf: &[u8], stage: DataInStage) {
294 #[cfg(feature = "defmt")]
295 trace!(" control in accept {:02x}", buf);
296 #[cfg(not(feature = "defmt"))]
297 trace!(" control in accept {:02x?}", buf);
298
299 let req_len = stage.length;
300 let len = buf.len().min(req_len);
301 let max_packet_size = self.control.max_packet_size();
302 let need_zlp = len != req_len && (len % usize::from(max_packet_size)) == 0;
303
304 let mut chunks = buf[0..len]
305 .chunks(max_packet_size)
306 .chain(need_zlp.then(|| -> &[u8] { &[] }));
307
308 while let Some(chunk) = chunks.next() {
309 match self.control.data_in(chunk, chunks.size_hint().0 == 0).await {
310 Ok(()) => {}
311 Err(e) => {
312 warn!("control accept_in failed: {:?}", e);
313 return;
314 }
315 }
316 }
317 }
318
319 pub(crate) async fn accept_in_writer(
320 &mut self,
321 req: Request,
322 stage: DataInStage,
323 f: impl FnOnce(&mut DescriptorWriter),
324 ) {
325 let mut buf = [0; 256];
326 let mut w = DescriptorWriter::new(&mut buf);
327 f(&mut w);
328 let pos = w.position().min(usize::from(req.length));
329 self.accept_in(&buf[..pos], stage).await
330 }
331
332 pub(crate) fn accept(&mut self, _: StatusStage) {
333 trace!(" control accept");
334 self.control.accept();
335 }
336
337 pub(crate) fn reject(&mut self) {
338 trace!(" control reject");
339 self.control.reject();
340 }
341}
diff --git a/embassy-usb/src/descriptor.rs b/embassy-usb/src/descriptor.rs
index dce326780..7f23fd921 100644
--- a/embassy-usb/src/descriptor.rs
+++ b/embassy-usb/src/descriptor.rs
@@ -244,6 +244,7 @@ impl<'a> DescriptorWriter<'a> {
244 } 244 }
245 245
246 /// Writes a string descriptor. 246 /// Writes a string descriptor.
247 #[allow(unused)]
247 pub(crate) fn string(&mut self, string: &str) { 248 pub(crate) fn string(&mut self, string: &str) {
248 let mut pos = self.position; 249 let mut pos = self.position;
249 250
diff --git a/embassy-usb/src/driver.rs b/embassy-usb/src/driver.rs
index e552dc7b6..57f2b0656 100644
--- a/embassy-usb/src/driver.rs
+++ b/embassy-usb/src/driver.rs
@@ -14,7 +14,7 @@ pub trait Driver<'a> {
14 14
15 /// Allocates an endpoint and specified endpoint parameters. This method is called by the device 15 /// Allocates an endpoint and specified endpoint parameters. This method is called by the device
16 /// and class implementations to allocate endpoints, and can only be called before 16 /// and class implementations to allocate endpoints, and can only be called before
17 /// [`enable`](UsbBus::enable) is called. 17 /// [`start`](UsbBus::start) is called.
18 /// 18 ///
19 /// # Arguments 19 /// # Arguments
20 /// 20 ///
@@ -25,7 +25,6 @@ pub trait Driver<'a> {
25 /// * `interval` - Polling interval parameter for interrupt endpoints. 25 /// * `interval` - Polling interval parameter for interrupt endpoints.
26 fn alloc_endpoint_out( 26 fn alloc_endpoint_out(
27 &mut self, 27 &mut self,
28 ep_addr: Option<EndpointAddress>,
29 ep_type: EndpointType, 28 ep_type: EndpointType,
30 max_packet_size: u16, 29 max_packet_size: u16,
31 interval: u8, 30 interval: u8,
@@ -33,20 +32,20 @@ pub trait Driver<'a> {
33 32
34 fn alloc_endpoint_in( 33 fn alloc_endpoint_in(
35 &mut self, 34 &mut self,
36 ep_addr: Option<EndpointAddress>,
37 ep_type: EndpointType, 35 ep_type: EndpointType,
38 max_packet_size: u16, 36 max_packet_size: u16,
39 interval: u8, 37 interval: u8,
40 ) -> Result<Self::EndpointIn, EndpointAllocError>; 38 ) -> Result<Self::EndpointIn, EndpointAllocError>;
41 39
42 fn alloc_control_pipe( 40 /// Start operation of the USB device.
43 &mut self, 41 ///
44 max_packet_size: u16, 42 /// This returns the `Bus` and `ControlPipe` instances that are used to operate
45 ) -> Result<Self::ControlPipe, EndpointAllocError>; 43 /// the USB device. Additionally, this makes all the previously allocated endpoints
46 44 /// start operating.
47 /// Enables and initializes the USB peripheral. Soon after enabling the device will be reset, so 45 ///
48 /// there is no need to perform a USB reset in this method. 46 /// This consumes the `Driver` instance, so it's no longer possible to allocate more
49 fn into_bus(self) -> Self::Bus; 47 /// endpoints.
48 fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe);
50 49
51 /// Indicates that `set_device_address` must be called before accepting the corresponding 50 /// Indicates that `set_device_address` must be called before accepting the corresponding
52 /// control transfer, not after. 51 /// control transfer, not after.
diff --git a/embassy-usb/src/lib.rs b/embassy-usb/src/lib.rs
index 3bfedc048..b135f5eb3 100644
--- a/embassy-usb/src/lib.rs
+++ b/embassy-usb/src/lib.rs
@@ -16,6 +16,7 @@ use embassy::util::{select, Either};
16use heapless::Vec; 16use heapless::Vec;
17 17
18use crate::descriptor_reader::foreach_endpoint; 18use crate::descriptor_reader::foreach_endpoint;
19use crate::driver::ControlPipe;
19 20
20use self::control::*; 21use self::control::*;
21use self::descriptor::*; 22use self::descriptor::*;
@@ -100,15 +101,19 @@ struct Interface<'d> {
100} 101}
101 102
102pub struct UsbDevice<'d, D: Driver<'d>> { 103pub struct UsbDevice<'d, D: Driver<'d>> {
104 control_buf: &'d mut [u8],
105 control: D::ControlPipe,
106 inner: Inner<'d, D>,
107}
108
109struct Inner<'d, D: Driver<'d>> {
103 bus: D::Bus, 110 bus: D::Bus,
104 handler: Option<&'d dyn DeviceStateHandler>, 111 handler: Option<&'d dyn DeviceStateHandler>,
105 control: ControlPipe<D::ControlPipe>,
106 112
107 config: Config<'d>, 113 config: Config<'d>,
108 device_descriptor: &'d [u8], 114 device_descriptor: &'d [u8],
109 config_descriptor: &'d [u8], 115 config_descriptor: &'d [u8],
110 bos_descriptor: &'d [u8], 116 bos_descriptor: &'d [u8],
111 control_buf: &'d mut [u8],
112 117
113 device_state: UsbDeviceState, 118 device_state: UsbDeviceState,
114 suspended: bool, 119 suspended: bool,
@@ -121,7 +126,7 @@ pub struct UsbDevice<'d, D: Driver<'d>> {
121 126
122impl<'d, D: Driver<'d>> UsbDevice<'d, D> { 127impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
123 pub(crate) fn build( 128 pub(crate) fn build(
124 mut driver: D, 129 driver: D,
125 config: Config<'d>, 130 config: Config<'d>,
126 handler: Option<&'d dyn DeviceStateHandler>, 131 handler: Option<&'d dyn DeviceStateHandler>,
127 device_descriptor: &'d [u8], 132 device_descriptor: &'d [u8],
@@ -130,29 +135,28 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
130 interfaces: Vec<Interface<'d>, MAX_INTERFACE_COUNT>, 135 interfaces: Vec<Interface<'d>, MAX_INTERFACE_COUNT>,
131 control_buf: &'d mut [u8], 136 control_buf: &'d mut [u8],
132 ) -> UsbDevice<'d, D> { 137 ) -> UsbDevice<'d, D> {
133 let control = driver 138 // Start the USB bus.
134 .alloc_control_pipe(config.max_packet_size_0 as u16)
135 .expect("failed to alloc control endpoint");
136
137 // Enable the USB bus.
138 // This prevent further allocation by consuming the driver. 139 // This prevent further allocation by consuming the driver.
139 let bus = driver.into_bus(); 140 let (bus, control) = driver.start(config.max_packet_size_0 as u16);
140 141
141 Self { 142 Self {
142 bus,
143 config,
144 handler,
145 control: ControlPipe::new(control),
146 device_descriptor,
147 config_descriptor,
148 bos_descriptor,
149 control_buf, 143 control_buf,
150 device_state: UsbDeviceState::Disabled, 144 control,
151 suspended: false, 145 inner: Inner {
152 remote_wakeup_enabled: false, 146 bus,
153 self_powered: false, 147 config,
154 pending_address: 0, 148 handler,
155 interfaces, 149 device_descriptor,
150 config_descriptor,
151 bos_descriptor,
152
153 device_state: UsbDeviceState::Disabled,
154 suspended: false,
155 remote_wakeup_enabled: false,
156 self_powered: false,
157 pending_address: 0,
158 interfaces,
159 },
156 } 160 }
157 } 161 }
158 162
@@ -176,42 +180,34 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
176 /// before calling any other `UsbDevice` methods to fully reset the 180 /// before calling any other `UsbDevice` methods to fully reset the
177 /// peripheral. 181 /// peripheral.
178 pub async fn run_until_suspend(&mut self) -> () { 182 pub async fn run_until_suspend(&mut self) -> () {
179 if self.device_state == UsbDeviceState::Disabled { 183 if self.inner.device_state == UsbDeviceState::Disabled {
180 self.bus.enable().await; 184 self.inner.bus.enable().await;
181 self.device_state = UsbDeviceState::Default; 185 self.inner.device_state = UsbDeviceState::Default;
182 186
183 if let Some(h) = &self.handler { 187 if let Some(h) = &self.inner.handler {
184 h.enabled(true); 188 h.enabled(true);
185 } 189 }
186 } 190 }
187 191
188 loop { 192 while !self.inner.suspended {
189 let control_fut = self.control.setup(); 193 let control_fut = self.control.setup();
190 let bus_fut = self.bus.poll(); 194 let bus_fut = self.inner.bus.poll();
191 match select(bus_fut, control_fut).await { 195 match select(bus_fut, control_fut).await {
192 Either::First(evt) => { 196 Either::First(evt) => self.inner.handle_bus_event(evt),
193 self.handle_bus_event(evt); 197 Either::Second(req) => self.handle_control(req).await,
194 if self.suspended {
195 return;
196 }
197 }
198 Either::Second(req) => match req {
199 Setup::DataIn(req, stage) => self.handle_control_in(req, stage).await,
200 Setup::DataOut(req, stage) => self.handle_control_out(req, stage).await,
201 },
202 } 198 }
203 } 199 }
204 } 200 }
205 201
206 /// Disables the USB peripheral. 202 /// Disables the USB peripheral.
207 pub async fn disable(&mut self) { 203 pub async fn disable(&mut self) {
208 if self.device_state != UsbDeviceState::Disabled { 204 if self.inner.device_state != UsbDeviceState::Disabled {
209 self.bus.disable().await; 205 self.inner.bus.disable().await;
210 self.device_state = UsbDeviceState::Disabled; 206 self.inner.device_state = UsbDeviceState::Disabled;
211 self.suspended = false; 207 self.inner.suspended = false;
212 self.remote_wakeup_enabled = false; 208 self.inner.remote_wakeup_enabled = false;
213 209
214 if let Some(h) = &self.handler { 210 if let Some(h) = &self.inner.handler {
215 h.enabled(false); 211 h.enabled(false);
216 } 212 }
217 } 213 }
@@ -221,9 +217,9 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
221 /// 217 ///
222 /// This future is cancel-safe. 218 /// This future is cancel-safe.
223 pub async fn wait_resume(&mut self) { 219 pub async fn wait_resume(&mut self) {
224 while self.suspended { 220 while self.inner.suspended {
225 let evt = self.bus.poll().await; 221 let evt = self.inner.bus.poll().await;
226 self.handle_bus_event(evt); 222 self.inner.handle_bus_event(evt);
227 } 223 }
228 } 224 }
229 225
@@ -236,11 +232,11 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
236 /// After dropping the future, [`UsbDevice::disable()`] should be called 232 /// After dropping the future, [`UsbDevice::disable()`] should be called
237 /// before calling any other `UsbDevice` methods to fully reset the peripheral. 233 /// before calling any other `UsbDevice` methods to fully reset the peripheral.
238 pub async fn remote_wakeup(&mut self) -> Result<(), RemoteWakeupError> { 234 pub async fn remote_wakeup(&mut self) -> Result<(), RemoteWakeupError> {
239 if self.suspended && self.remote_wakeup_enabled { 235 if self.inner.suspended && self.inner.remote_wakeup_enabled {
240 self.bus.remote_wakeup().await?; 236 self.inner.bus.remote_wakeup().await?;
241 self.suspended = false; 237 self.inner.suspended = false;
242 238
243 if let Some(h) = &self.handler { 239 if let Some(h) = &self.inner.handler {
244 h.suspended(false); 240 h.suspended(false);
245 } 241 }
246 242
@@ -250,6 +246,88 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
250 } 246 }
251 } 247 }
252 248
249 async fn handle_control(&mut self, req: Request) {
250 trace!("control request: {:02x}", req);
251
252 match req.direction {
253 UsbDirection::In => self.handle_control_in(req).await,
254 UsbDirection::Out => self.handle_control_out(req).await,
255 }
256 }
257
258 async fn handle_control_in(&mut self, req: Request) {
259 let mut resp_length = req.length as usize;
260 let max_packet_size = self.control.max_packet_size();
261
262 // If we don't have an address yet, respond with max 1 packet.
263 // The host doesn't know our EP0 max packet size yet, and might assume
264 // a full-length packet is a short packet, thinking we're done sending data.
265 // See https://github.com/hathach/tinyusb/issues/184
266 const DEVICE_DESCRIPTOR_LEN: usize = 18;
267 if self.inner.pending_address == 0
268 && max_packet_size < DEVICE_DESCRIPTOR_LEN
269 && (max_packet_size as usize) < resp_length
270 {
271 trace!("received control req while not addressed: capping response to 1 packet.");
272 resp_length = max_packet_size;
273 }
274
275 match self.inner.handle_control_in(req, &mut self.control_buf) {
276 InResponse::Accepted(data) => {
277 let len = data.len().min(resp_length);
278 let need_zlp = len != resp_length && (len % usize::from(max_packet_size)) == 0;
279
280 let mut chunks = data[0..len]
281 .chunks(max_packet_size)
282 .chain(need_zlp.then(|| -> &[u8] { &[] }));
283
284 while let Some(chunk) = chunks.next() {
285 match self.control.data_in(chunk, chunks.size_hint().0 == 0).await {
286 Ok(()) => {}
287 Err(e) => {
288 warn!("control accept_in failed: {:?}", e);
289 return;
290 }
291 }
292 }
293 }
294 InResponse::Rejected => self.control.reject(),
295 }
296 }
297
298 async fn handle_control_out(&mut self, req: Request) {
299 let req_length = req.length as usize;
300 let max_packet_size = self.control.max_packet_size();
301 let mut total = 0;
302
303 for chunk in self.control_buf[..req_length].chunks_mut(max_packet_size) {
304 let size = match self.control.data_out(chunk).await {
305 Ok(x) => x,
306 Err(e) => {
307 warn!("usb: failed to read CONTROL OUT data stage: {:?}", e);
308 return;
309 }
310 };
311 total += size;
312 if size < max_packet_size || total == req_length {
313 break;
314 }
315 }
316
317 let data = &self.control_buf[0..total];
318 #[cfg(feature = "defmt")]
319 trace!(" control out data: {:02x}", data);
320 #[cfg(not(feature = "defmt"))]
321 trace!(" control out data: {:02x?}", data);
322
323 match self.inner.handle_control_out(req, data) {
324 OutResponse::Accepted => self.control.accept(),
325 OutResponse::Rejected => self.control.reject(),
326 }
327 }
328}
329
330impl<'d, D: Driver<'d>> Inner<'d, D> {
253 fn handle_bus_event(&mut self, evt: Event) { 331 fn handle_bus_event(&mut self, evt: Event) {
254 match evt { 332 match evt {
255 Event::Reset => { 333 Event::Reset => {
@@ -288,18 +366,10 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
288 } 366 }
289 } 367 }
290 368
291 async fn handle_control_out(&mut self, req: Request, stage: DataOutStage) { 369 fn handle_control_out(&mut self, req: Request, data: &[u8]) -> OutResponse {
292 const CONFIGURATION_NONE_U16: u16 = CONFIGURATION_NONE as u16; 370 const CONFIGURATION_NONE_U16: u16 = CONFIGURATION_NONE as u16;
293 const CONFIGURATION_VALUE_U16: u16 = CONFIGURATION_VALUE as u16; 371 const CONFIGURATION_VALUE_U16: u16 = CONFIGURATION_VALUE as u16;
294 372
295 let (data, stage) = match self.control.data_out(self.control_buf, stage).await {
296 Ok(data) => data,
297 Err(_) => {
298 warn!("usb: failed to read CONTROL OUT data stage.");
299 return;
300 }
301 };
302
303 match (req.request_type, req.recipient) { 373 match (req.request_type, req.recipient) {
304 (RequestType::Standard, Recipient::Device) => match (req.request, req.value) { 374 (RequestType::Standard, Recipient::Device) => match (req.request, req.value) {
305 (Request::CLEAR_FEATURE, Request::FEATURE_DEVICE_REMOTE_WAKEUP) => { 375 (Request::CLEAR_FEATURE, Request::FEATURE_DEVICE_REMOTE_WAKEUP) => {
@@ -307,14 +377,14 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
307 if let Some(h) = &self.handler { 377 if let Some(h) = &self.handler {
308 h.remote_wakeup_enabled(false); 378 h.remote_wakeup_enabled(false);
309 } 379 }
310 self.control.accept(stage) 380 OutResponse::Accepted
311 } 381 }
312 (Request::SET_FEATURE, Request::FEATURE_DEVICE_REMOTE_WAKEUP) => { 382 (Request::SET_FEATURE, Request::FEATURE_DEVICE_REMOTE_WAKEUP) => {
313 self.remote_wakeup_enabled = true; 383 self.remote_wakeup_enabled = true;
314 if let Some(h) = &self.handler { 384 if let Some(h) = &self.handler {
315 h.remote_wakeup_enabled(true); 385 h.remote_wakeup_enabled(true);
316 } 386 }
317 self.control.accept(stage) 387 OutResponse::Accepted
318 } 388 }
319 (Request::SET_ADDRESS, addr @ 1..=127) => { 389 (Request::SET_ADDRESS, addr @ 1..=127) => {
320 self.pending_address = addr as u8; 390 self.pending_address = addr as u8;
@@ -323,7 +393,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
323 if let Some(h) = &self.handler { 393 if let Some(h) = &self.handler {
324 h.addressed(self.pending_address); 394 h.addressed(self.pending_address);
325 } 395 }
326 self.control.accept(stage) 396 OutResponse::Accepted
327 } 397 }
328 (Request::SET_CONFIGURATION, CONFIGURATION_VALUE_U16) => { 398 (Request::SET_CONFIGURATION, CONFIGURATION_VALUE_U16) => {
329 debug!("SET_CONFIGURATION: configured"); 399 debug!("SET_CONFIGURATION: configured");
@@ -344,10 +414,10 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
344 h.configured(true); 414 h.configured(true);
345 } 415 }
346 416
347 self.control.accept(stage) 417 OutResponse::Accepted
348 } 418 }
349 (Request::SET_CONFIGURATION, CONFIGURATION_NONE_U16) => match self.device_state { 419 (Request::SET_CONFIGURATION, CONFIGURATION_NONE_U16) => match self.device_state {
350 UsbDeviceState::Default => self.control.accept(stage), 420 UsbDeviceState::Default => OutResponse::Accepted,
351 _ => { 421 _ => {
352 debug!("SET_CONFIGURATION: unconfigured"); 422 debug!("SET_CONFIGURATION: unconfigured");
353 self.device_state = UsbDeviceState::Addressed; 423 self.device_state = UsbDeviceState::Addressed;
@@ -363,15 +433,15 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
363 h.configured(false); 433 h.configured(false);
364 } 434 }
365 435
366 self.control.accept(stage) 436 OutResponse::Accepted
367 } 437 }
368 }, 438 },
369 _ => self.control.reject(), 439 _ => OutResponse::Rejected,
370 }, 440 },
371 (RequestType::Standard, Recipient::Interface) => { 441 (RequestType::Standard, Recipient::Interface) => {
372 let iface = match self.interfaces.get_mut(req.index as usize) { 442 let iface = match self.interfaces.get_mut(req.index as usize) {
373 Some(iface) => iface, 443 Some(iface) => iface,
374 None => return self.control.reject(), 444 None => return OutResponse::Rejected,
375 }; 445 };
376 446
377 match req.request { 447 match req.request {
@@ -380,7 +450,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
380 450
381 if new_altsetting >= iface.num_alt_settings { 451 if new_altsetting >= iface.num_alt_settings {
382 warn!("SET_INTERFACE: trying to select alt setting out of range."); 452 warn!("SET_INTERFACE: trying to select alt setting out of range.");
383 return self.control.reject(); 453 return OutResponse::Rejected;
384 } 454 }
385 455
386 iface.current_alt_setting = new_altsetting; 456 iface.current_alt_setting = new_altsetting;
@@ -402,55 +472,39 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
402 if let Some(handler) = &mut iface.handler { 472 if let Some(handler) = &mut iface.handler {
403 handler.set_alternate_setting(new_altsetting); 473 handler.set_alternate_setting(new_altsetting);
404 } 474 }
405 self.control.accept(stage) 475 OutResponse::Accepted
406 } 476 }
407 _ => self.control.reject(), 477 _ => OutResponse::Rejected,
408 } 478 }
409 } 479 }
410 (RequestType::Standard, Recipient::Endpoint) => match (req.request, req.value) { 480 (RequestType::Standard, Recipient::Endpoint) => match (req.request, req.value) {
411 (Request::SET_FEATURE, Request::FEATURE_ENDPOINT_HALT) => { 481 (Request::SET_FEATURE, Request::FEATURE_ENDPOINT_HALT) => {
412 let ep_addr = ((req.index as u8) & 0x8f).into(); 482 let ep_addr = ((req.index as u8) & 0x8f).into();
413 self.bus.endpoint_set_stalled(ep_addr, true); 483 self.bus.endpoint_set_stalled(ep_addr, true);
414 self.control.accept(stage) 484 OutResponse::Accepted
415 } 485 }
416 (Request::CLEAR_FEATURE, Request::FEATURE_ENDPOINT_HALT) => { 486 (Request::CLEAR_FEATURE, Request::FEATURE_ENDPOINT_HALT) => {
417 let ep_addr = ((req.index as u8) & 0x8f).into(); 487 let ep_addr = ((req.index as u8) & 0x8f).into();
418 self.bus.endpoint_set_stalled(ep_addr, false); 488 self.bus.endpoint_set_stalled(ep_addr, false);
419 self.control.accept(stage) 489 OutResponse::Accepted
420 } 490 }
421 _ => self.control.reject(), 491 _ => OutResponse::Rejected,
422 }, 492 },
423 (RequestType::Class, Recipient::Interface) => { 493 (RequestType::Class, Recipient::Interface) => {
424 let iface = match self.interfaces.get_mut(req.index as usize) { 494 let iface = match self.interfaces.get_mut(req.index as usize) {
425 Some(iface) => iface, 495 Some(iface) => iface,
426 None => return self.control.reject(), 496 None => return OutResponse::Rejected,
427 }; 497 };
428 match &mut iface.handler { 498 match &mut iface.handler {
429 Some(handler) => match handler.control_out(req, data) { 499 Some(handler) => handler.control_out(req, data),
430 OutResponse::Accepted => self.control.accept(stage), 500 None => OutResponse::Rejected,
431 OutResponse::Rejected => self.control.reject(),
432 },
433 None => self.control.reject(),
434 } 501 }
435 } 502 }
436 _ => self.control.reject(), 503 _ => OutResponse::Rejected,
437 } 504 }
438 } 505 }
439 506
440 async fn handle_control_in(&mut self, req: Request, mut stage: DataInStage) { 507 fn handle_control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> {
441 // If we don't have an address yet, respond with max 1 packet.
442 // The host doesn't know our EP0 max packet size yet, and might assume
443 // a full-length packet is a short packet, thinking we're done sending data.
444 // See https://github.com/hathach/tinyusb/issues/184
445 const DEVICE_DESCRIPTOR_LEN: u8 = 18;
446 if self.pending_address == 0
447 && self.config.max_packet_size_0 < DEVICE_DESCRIPTOR_LEN
448 && (self.config.max_packet_size_0 as usize) < stage.length
449 {
450 trace!("received control req while not addressed: capping response to 1 packet.");
451 stage.length = self.config.max_packet_size_0 as _;
452 }
453
454 match (req.request_type, req.recipient) { 508 match (req.request_type, req.recipient) {
455 (RequestType::Standard, Recipient::Device) => match req.request { 509 (RequestType::Standard, Recipient::Device) => match req.request {
456 Request::GET_STATUS => { 510 Request::GET_STATUS => {
@@ -461,42 +515,41 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
461 if self.remote_wakeup_enabled { 515 if self.remote_wakeup_enabled {
462 status |= 0x0002; 516 status |= 0x0002;
463 } 517 }
464 self.control.accept_in(&status.to_le_bytes(), stage).await 518 buf[..2].copy_from_slice(&status.to_le_bytes());
519 InResponse::Accepted(&buf[..2])
465 } 520 }
466 Request::GET_DESCRIPTOR => self.handle_get_descriptor(req, stage).await, 521 Request::GET_DESCRIPTOR => self.handle_get_descriptor(req, buf),
467 Request::GET_CONFIGURATION => { 522 Request::GET_CONFIGURATION => {
468 let status = match self.device_state { 523 let status = match self.device_state {
469 UsbDeviceState::Configured => CONFIGURATION_VALUE, 524 UsbDeviceState::Configured => CONFIGURATION_VALUE,
470 _ => CONFIGURATION_NONE, 525 _ => CONFIGURATION_NONE,
471 }; 526 };
472 self.control.accept_in(&status.to_le_bytes(), stage).await 527 buf[0] = status;
528 InResponse::Accepted(&buf[..1])
473 } 529 }
474 _ => self.control.reject(), 530 _ => InResponse::Rejected,
475 }, 531 },
476 (RequestType::Standard, Recipient::Interface) => { 532 (RequestType::Standard, Recipient::Interface) => {
477 let iface = match self.interfaces.get_mut(req.index as usize) { 533 let iface = match self.interfaces.get_mut(req.index as usize) {
478 Some(iface) => iface, 534 Some(iface) => iface,
479 None => return self.control.reject(), 535 None => return InResponse::Rejected,
480 }; 536 };
481 537
482 match req.request { 538 match req.request {
483 Request::GET_STATUS => { 539 Request::GET_STATUS => {
484 let status: u16 = 0; 540 let status: u16 = 0;
485 self.control.accept_in(&status.to_le_bytes(), stage).await 541 buf[..2].copy_from_slice(&status.to_le_bytes());
542 InResponse::Accepted(&buf[..2])
486 } 543 }
487 Request::GET_INTERFACE => { 544 Request::GET_INTERFACE => {
488 self.control 545 buf[0] = iface.current_alt_setting;
489 .accept_in(&[iface.current_alt_setting], stage) 546 InResponse::Accepted(&buf[..1])
490 .await;
491 } 547 }
492 Request::GET_DESCRIPTOR => match &mut iface.handler { 548 Request::GET_DESCRIPTOR => match &mut iface.handler {
493 Some(handler) => match handler.get_descriptor(req, self.control_buf) { 549 Some(handler) => handler.get_descriptor(req, buf),
494 InResponse::Accepted(data) => self.control.accept_in(data, stage).await, 550 None => InResponse::Rejected,
495 InResponse::Rejected => self.control.reject(),
496 },
497 None => self.control.reject(),
498 }, 551 },
499 _ => self.control.reject(), 552 _ => InResponse::Rejected,
500 } 553 }
501 } 554 }
502 (RequestType::Standard, Recipient::Endpoint) => match req.request { 555 (RequestType::Standard, Recipient::Endpoint) => match req.request {
@@ -506,44 +559,40 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
506 if self.bus.endpoint_is_stalled(ep_addr) { 559 if self.bus.endpoint_is_stalled(ep_addr) {
507 status |= 0x0001; 560 status |= 0x0001;
508 } 561 }
509 self.control.accept_in(&status.to_le_bytes(), stage).await 562 buf[..2].copy_from_slice(&status.to_le_bytes());
563 InResponse::Accepted(&buf[..2])
510 } 564 }
511 _ => self.control.reject(), 565 _ => InResponse::Rejected,
512 }, 566 },
513 (RequestType::Class, Recipient::Interface) => { 567 (RequestType::Class, Recipient::Interface) => {
514 let iface = match self.interfaces.get_mut(req.index as usize) { 568 let iface = match self.interfaces.get_mut(req.index as usize) {
515 Some(iface) => iface, 569 Some(iface) => iface,
516 None => return self.control.reject(), 570 None => return InResponse::Rejected,
517 }; 571 };
518 572
519 match &mut iface.handler { 573 match &mut iface.handler {
520 Some(handler) => match handler.control_in(req, self.control_buf) { 574 Some(handler) => handler.control_in(req, buf),
521 InResponse::Accepted(data) => self.control.accept_in(data, stage).await, 575 None => InResponse::Rejected,
522 InResponse::Rejected => self.control.reject(),
523 },
524 None => self.control.reject(),
525 } 576 }
526 } 577 }
527 _ => self.control.reject(), 578 _ => InResponse::Rejected,
528 } 579 }
529 } 580 }
530 581
531 async fn handle_get_descriptor(&mut self, req: Request, stage: DataInStage) { 582 fn handle_get_descriptor<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> InResponse<'a> {
532 let (dtype, index) = req.descriptor_type_index(); 583 let (dtype, index) = req.descriptor_type_index();
533 584
534 match dtype { 585 match dtype {
535 descriptor_type::BOS => self.control.accept_in(self.bos_descriptor, stage).await, 586 descriptor_type::BOS => InResponse::Accepted(self.bos_descriptor),
536 descriptor_type::DEVICE => self.control.accept_in(self.device_descriptor, stage).await, 587 descriptor_type::DEVICE => InResponse::Accepted(self.device_descriptor),
537 descriptor_type::CONFIGURATION => { 588 descriptor_type::CONFIGURATION => InResponse::Accepted(self.config_descriptor),
538 self.control.accept_in(self.config_descriptor, stage).await
539 }
540 descriptor_type::STRING => { 589 descriptor_type::STRING => {
541 if index == 0 { 590 if index == 0 {
542 self.control 591 buf[0] = 4; // len
543 .accept_in_writer(req, stage, |w| { 592 buf[1] = descriptor_type::STRING;
544 w.write(descriptor_type::STRING, &lang_id::ENGLISH_US.to_le_bytes()); 593 buf[2] = lang_id::ENGLISH_US as u8;
545 }) 594 buf[3] = (lang_id::ENGLISH_US >> 8) as u8;
546 .await 595 InResponse::Accepted(&buf[..4])
547 } else { 596 } else {
548 let s = match index { 597 let s = match index {
549 STRING_INDEX_MANUFACTURER => self.config.manufacturer, 598 STRING_INDEX_MANUFACTURER => self.config.manufacturer,
@@ -565,7 +614,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
565 if let Some(handler) = &mut iface.handler { 614 if let Some(handler) = &mut iface.handler {
566 let index = StringIndex::new(index); 615 let index = StringIndex::new(index);
567 let lang_id = req.index; 616 let lang_id = req.index;
568 handler.get_string(index, lang_id, self.control_buf) 617 handler.get_string(index, lang_id)
569 } else { 618 } else {
570 warn!("String requested to an interface with no handler."); 619 warn!("String requested to an interface with no handler.");
571 None 620 None
@@ -578,15 +627,29 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
578 }; 627 };
579 628
580 if let Some(s) = s { 629 if let Some(s) = s {
581 self.control 630 if buf.len() < 2 {
582 .accept_in_writer(req, stage, |w| w.string(s)) 631 panic!("control buffer too small");
583 .await 632 }
633
634 buf[1] = descriptor_type::STRING;
635 let mut pos = 2;
636 for c in s.encode_utf16() {
637 if pos >= buf.len() {
638 panic!("control buffer too small");
639 }
640
641 buf[pos..pos + 2].copy_from_slice(&c.to_le_bytes());
642 pos += 2;
643 }
644
645 buf[0] = pos as u8;
646 InResponse::Accepted(&buf[..pos])
584 } else { 647 } else {
585 self.control.reject() 648 InResponse::Rejected
586 } 649 }
587 } 650 }
588 } 651 }
589 _ => self.control.reject(), 652 _ => InResponse::Rejected,
590 } 653 }
591 } 654 }
592} 655}
diff --git a/examples/nrf/src/bin/usb_hid_keyboard.rs b/examples/nrf/src/bin/usb_hid_keyboard.rs
index 3852dd8da..d855a3a57 100644
--- a/examples/nrf/src/bin/usb_hid_keyboard.rs
+++ b/examples/nrf/src/bin/usb_hid_keyboard.rs
@@ -71,7 +71,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
71 let mut device_descriptor = [0; 256]; 71 let mut device_descriptor = [0; 256];
72 let mut config_descriptor = [0; 256]; 72 let mut config_descriptor = [0; 256];
73 let mut bos_descriptor = [0; 256]; 73 let mut bos_descriptor = [0; 256];
74 let mut control_buf = [0; 16]; 74 let mut control_buf = [0; 64];
75 let request_handler = MyRequestHandler {}; 75 let request_handler = MyRequestHandler {};
76 let device_state_handler = MyDeviceStateHandler::new(); 76 let device_state_handler = MyDeviceStateHandler::new();
77 77
diff --git a/examples/nrf/src/bin/usb_hid_mouse.rs b/examples/nrf/src/bin/usb_hid_mouse.rs
index e70dc51a5..c526c1c6f 100644
--- a/examples/nrf/src/bin/usb_hid_mouse.rs
+++ b/examples/nrf/src/bin/usb_hid_mouse.rs
@@ -50,7 +50,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
50 let mut device_descriptor = [0; 256]; 50 let mut device_descriptor = [0; 256];
51 let mut config_descriptor = [0; 256]; 51 let mut config_descriptor = [0; 256];
52 let mut bos_descriptor = [0; 256]; 52 let mut bos_descriptor = [0; 256];
53 let mut control_buf = [0; 16]; 53 let mut control_buf = [0; 64];
54 let request_handler = MyRequestHandler {}; 54 let request_handler = MyRequestHandler {};
55 55
56 let mut state = State::new(); 56 let mut state = State::new();
diff --git a/examples/nrf/src/bin/usb_serial.rs b/examples/nrf/src/bin/usb_serial.rs
index bc41c2acf..2551c4ba1 100644
--- a/examples/nrf/src/bin/usb_serial.rs
+++ b/examples/nrf/src/bin/usb_serial.rs
@@ -43,12 +43,19 @@ async fn main(_spawner: Spawner, p: Peripherals) {
43 config.max_power = 100; 43 config.max_power = 100;
44 config.max_packet_size_0 = 64; 44 config.max_packet_size_0 = 64;
45 45
46 // Required for windows compatiblity.
47 // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help
48 config.device_class = 0xEF;
49 config.device_sub_class = 0x02;
50 config.device_protocol = 0x01;
51 config.composite_with_iads = true;
52
46 // Create embassy-usb DeviceBuilder using the driver and config. 53 // Create embassy-usb DeviceBuilder using the driver and config.
47 // It needs some buffers for building the descriptors. 54 // It needs some buffers for building the descriptors.
48 let mut device_descriptor = [0; 256]; 55 let mut device_descriptor = [0; 256];
49 let mut config_descriptor = [0; 256]; 56 let mut config_descriptor = [0; 256];
50 let mut bos_descriptor = [0; 256]; 57 let mut bos_descriptor = [0; 256];
51 let mut control_buf = [0; 7]; 58 let mut control_buf = [0; 64];
52 59
53 let mut state = State::new(); 60 let mut state = State::new();
54 61
diff --git a/examples/nrf/src/bin/usb_serial_multitask.rs b/examples/nrf/src/bin/usb_serial_multitask.rs
index 31e0af483..0e82ba313 100644
--- a/examples/nrf/src/bin/usb_serial_multitask.rs
+++ b/examples/nrf/src/bin/usb_serial_multitask.rs
@@ -60,11 +60,18 @@ async fn main(spawner: Spawner, p: Peripherals) {
60 config.max_power = 100; 60 config.max_power = 100;
61 config.max_packet_size_0 = 64; 61 config.max_packet_size_0 = 64;
62 62
63 // Required for windows compatiblity.
64 // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help
65 config.device_class = 0xEF;
66 config.device_sub_class = 0x02;
67 config.device_protocol = 0x01;
68 config.composite_with_iads = true;
69
63 struct Resources { 70 struct Resources {
64 device_descriptor: [u8; 256], 71 device_descriptor: [u8; 256],
65 config_descriptor: [u8; 256], 72 config_descriptor: [u8; 256],
66 bos_descriptor: [u8; 256], 73 bos_descriptor: [u8; 256],
67 control_buf: [u8; 7], 74 control_buf: [u8; 64],
68 serial_state: State<'static>, 75 serial_state: State<'static>,
69 } 76 }
70 static RESOURCES: Forever<Resources> = Forever::new(); 77 static RESOURCES: Forever<Resources> = Forever::new();
@@ -72,7 +79,7 @@ async fn main(spawner: Spawner, p: Peripherals) {
72 device_descriptor: [0; 256], 79 device_descriptor: [0; 256],
73 config_descriptor: [0; 256], 80 config_descriptor: [0; 256],
74 bos_descriptor: [0; 256], 81 bos_descriptor: [0; 256],
75 control_buf: [0; 7], 82 control_buf: [0; 64],
76 serial_state: State::new(), 83 serial_state: State::new(),
77 }); 84 });
78 85