diff options
| author | Henrik Alsér <[email protected]> | 2022-05-12 15:24:46 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-05-12 15:24:46 +0200 |
| commit | 0be9184efc8f814a19081c2176b8317bd5217f0f (patch) | |
| tree | 5b9469de15c0a1cc6e106a9a7455602e3bfaad17 | |
| parent | 1ca5475010a1cae6ebc55a27948ca4320decd5cd (diff) | |
| parent | 30d4d0e9d78681e16a68ff953c61b96c9863bfc6 (diff) | |
Merge branch 'embassy-rs:master' into qdec
| -rwxr-xr-x | ci.sh | 1 | ||||
| -rw-r--r-- | embassy-nrf/src/usb.rs | 94 | ||||
| -rw-r--r-- | embassy-rp/Cargo.toml | 2 | ||||
| -rw-r--r-- | embassy-rp/src/gpio.rs | 5 | ||||
| -rw-r--r-- | embassy-stm32/src/exti.rs | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/gpio.rs | 11 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/f3.rs | 26 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/f7.rs | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/mod.rs | 4 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/mod.rs | 6 | ||||
| -rw-r--r-- | embassy-stm32/src/usb_otg.rs | 4 | ||||
| -rw-r--r-- | embassy-usb-ncm/src/lib.rs | 14 | ||||
| -rw-r--r-- | embassy-usb/src/builder.rs | 14 | ||||
| -rw-r--r-- | embassy-usb/src/control.rs | 150 | ||||
| -rw-r--r-- | embassy-usb/src/descriptor.rs | 1 | ||||
| -rw-r--r-- | embassy-usb/src/driver.rs | 21 | ||||
| -rw-r--r-- | embassy-usb/src/lib.rs | 335 | ||||
| -rw-r--r-- | examples/nrf/src/bin/usb_hid_keyboard.rs | 2 | ||||
| -rw-r--r-- | examples/nrf/src/bin/usb_hid_mouse.rs | 2 | ||||
| -rw-r--r-- | examples/nrf/src/bin/usb_serial.rs | 9 | ||||
| -rw-r--r-- | examples/nrf/src/bin/usb_serial_multitask.rs | 11 |
21 files changed, 317 insertions, 399 deletions
| @@ -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 | ||
| 797 | struct Allocator { | 784 | struct 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 | ||
| 803 | impl Allocator { | 788 | impl 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. |
| 21 | unstable-pac = [] | 21 | unstable-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; | |||
| 4 | use core::mem::MaybeUninit; | 4 | use 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; | |||
| 3 | use embassy_hal_common::unborrow; | 3 | use embassy_hal_common::unborrow; |
| 4 | 4 | ||
| 5 | use crate::gpio::sealed::AFType; | 5 | use crate::gpio::sealed::AFType; |
| 6 | use crate::gpio::Speed; | ||
| 7 | use crate::{peripherals, rcc::RccPeripheral}; | 6 | use crate::{peripherals, rcc::RccPeripheral}; |
| 8 | 7 | ||
| 9 | macro_rules! config_ulpi_pins { | 8 | macro_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 { | |||
| 133 | struct CommControl<'a> { | 133 | struct 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 | ||
| 138 | impl<'d> ControlHandler for CommControl<'d> { | 139 | impl<'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 @@ | |||
| 1 | use core::mem; | 1 | use core::mem; |
| 2 | 2 | ||
| 3 | use crate::descriptor::DescriptorWriter; | ||
| 4 | use crate::driver::{self, EndpointError}; | ||
| 5 | |||
| 6 | use super::types::*; | 3 | use 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))] | ||
| 211 | pub(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))] | ||
| 218 | pub(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))] | ||
| 225 | pub(crate) struct StatusStage {} | ||
| 226 | |||
| 227 | #[derive(Debug)] | ||
| 228 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 229 | pub(crate) enum Setup { | ||
| 230 | DataIn(Request, DataInStage), | ||
| 231 | DataOut(Request, DataOutStage), | ||
| 232 | } | ||
| 233 | |||
| 234 | pub(crate) struct ControlPipe<C: driver::ControlPipe> { | ||
| 235 | control: C, | ||
| 236 | } | ||
| 237 | |||
| 238 | impl<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}; | |||
| 16 | use heapless::Vec; | 16 | use heapless::Vec; |
| 17 | 17 | ||
| 18 | use crate::descriptor_reader::foreach_endpoint; | 18 | use crate::descriptor_reader::foreach_endpoint; |
| 19 | use crate::driver::ControlPipe; | ||
| 19 | 20 | ||
| 20 | use self::control::*; | 21 | use self::control::*; |
| 21 | use self::descriptor::*; | 22 | use self::descriptor::*; |
| @@ -100,15 +101,19 @@ struct Interface<'d> { | |||
| 100 | } | 101 | } |
| 101 | 102 | ||
| 102 | pub struct UsbDevice<'d, D: Driver<'d>> { | 103 | pub struct UsbDevice<'d, D: Driver<'d>> { |
| 104 | control_buf: &'d mut [u8], | ||
| 105 | control: D::ControlPipe, | ||
| 106 | inner: Inner<'d, D>, | ||
| 107 | } | ||
| 108 | |||
| 109 | struct 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 | ||
| 122 | impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | 127 | impl<'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 | |||
| 330 | impl<'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 | ||
