diff options
| author | alexmoon <[email protected]> | 2022-04-13 16:04:31 -0400 |
|---|---|---|
| committer | alexmoon <[email protected]> | 2022-04-13 16:04:31 -0400 |
| commit | b0725c14d36cb9c508cb9fcec5b92ca9e0148583 (patch) | |
| tree | 1faa806fdba3ee023b4a5f31b3065aff5c9d51c8 /embassy-usb/src/lib.rs | |
| parent | ff7c6b350e2338a0b1e4327f4b2eb0435468f313 (diff) | |
Split UsbDevice::run into run and run_until_suspend
Diffstat (limited to 'embassy-usb/src/lib.rs')
| -rw-r--r-- | embassy-usb/src/lib.rs | 129 |
1 files changed, 81 insertions, 48 deletions
diff --git a/embassy-usb/src/lib.rs b/embassy-usb/src/lib.rs index ccea8bc7a..baeca099f 100644 --- a/embassy-usb/src/lib.rs +++ b/embassy-usb/src/lib.rs | |||
| @@ -100,7 +100,6 @@ pub struct UsbDevice<'d, D: Driver<'d>> { | |||
| 100 | 100 | ||
| 101 | device_state: UsbDeviceState, | 101 | device_state: UsbDeviceState, |
| 102 | suspended: bool, | 102 | suspended: bool, |
| 103 | in_control_handler: bool, | ||
| 104 | remote_wakeup_enabled: bool, | 103 | remote_wakeup_enabled: bool, |
| 105 | self_powered: bool, | 104 | self_powered: bool, |
| 106 | pending_address: u8, | 105 | pending_address: u8, |
| @@ -138,7 +137,6 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 138 | control_buf, | 137 | control_buf, |
| 139 | device_state: UsbDeviceState::Disabled, | 138 | device_state: UsbDeviceState::Disabled, |
| 140 | suspended: false, | 139 | suspended: false, |
| 141 | in_control_handler: false, | ||
| 142 | remote_wakeup_enabled: false, | 140 | remote_wakeup_enabled: false, |
| 143 | self_powered: false, | 141 | self_powered: false, |
| 144 | pending_address: 0, | 142 | pending_address: 0, |
| @@ -146,7 +144,26 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 146 | } | 144 | } |
| 147 | } | 145 | } |
| 148 | 146 | ||
| 147 | /// Runs the `UsbDevice` forever. | ||
| 148 | /// | ||
| 149 | /// This future may leave the bus in an invalid state if it is dropped. | ||
| 150 | /// After dropping the future, [`UsbDevice::disable()`] should be called | ||
| 151 | /// before calling any other `UsbDevice` methods to fully reset the | ||
| 152 | /// peripheral. | ||
| 149 | pub async fn run(&mut self) -> ! { | 153 | pub async fn run(&mut self) -> ! { |
| 154 | loop { | ||
| 155 | self.run_until_suspend().await; | ||
| 156 | self.wait_resume().await; | ||
| 157 | } | ||
| 158 | } | ||
| 159 | |||
| 160 | /// Runs the `UsbDevice` until the bus is suspended. | ||
| 161 | /// | ||
| 162 | /// This future may leave the bus in an invalid state if it is dropped. | ||
| 163 | /// After dropping the future, [`UsbDevice::disable()`] should be called | ||
| 164 | /// before calling any other `UsbDevice` methods to fully reset the | ||
| 165 | /// peripheral. | ||
| 166 | pub async fn run_until_suspend(&mut self) -> () { | ||
| 150 | if self.device_state == UsbDeviceState::Disabled { | 167 | if self.device_state == UsbDeviceState::Disabled { |
| 151 | self.bus.enable().await; | 168 | self.bus.enable().await; |
| 152 | self.device_state = UsbDeviceState::Default; | 169 | self.device_state = UsbDeviceState::Default; |
| @@ -154,66 +171,33 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 154 | if let Some(h) = &self.handler { | 171 | if let Some(h) = &self.handler { |
| 155 | h.enabled(true); | 172 | h.enabled(true); |
| 156 | } | 173 | } |
| 157 | } else if self.in_control_handler { | ||
| 158 | warn!("usb: control request interrupted"); | ||
| 159 | self.control.reject(); | ||
| 160 | self.in_control_handler = false; | ||
| 161 | } | 174 | } |
| 162 | 175 | ||
| 163 | loop { | 176 | loop { |
| 164 | let control_fut = self.control.setup(); | 177 | let control_fut = self.control.setup(); |
| 165 | let bus_fut = self.bus.poll(); | 178 | let bus_fut = self.bus.poll(); |
| 166 | match select(bus_fut, control_fut).await { | 179 | match select(bus_fut, control_fut).await { |
| 167 | Either::First(evt) => match evt { | 180 | Either::First(evt) => { |
| 168 | Event::Reset => { | 181 | self.handle_bus_event(evt); |
| 169 | trace!("usb: reset"); | 182 | if self.suspended { |
| 170 | self.device_state = UsbDeviceState::Default; | 183 | return; |
| 171 | self.suspended = false; | ||
| 172 | self.remote_wakeup_enabled = false; | ||
| 173 | self.pending_address = 0; | ||
| 174 | |||
| 175 | for (_, h) in self.interfaces.iter_mut() { | ||
| 176 | h.reset(); | ||
| 177 | } | ||
| 178 | |||
| 179 | if let Some(h) = &self.handler { | ||
| 180 | h.reset(); | ||
| 181 | } | ||
| 182 | } | ||
| 183 | Event::Resume => { | ||
| 184 | trace!("usb: resume"); | ||
| 185 | self.suspended = false; | ||
| 186 | if let Some(h) = &self.handler { | ||
| 187 | h.suspended(false); | ||
| 188 | } | ||
| 189 | } | ||
| 190 | Event::Suspend => { | ||
| 191 | trace!("usb: suspend"); | ||
| 192 | self.suspended = true; | ||
| 193 | if let Some(h) = &self.handler { | ||
| 194 | h.suspended(true); | ||
| 195 | } | ||
| 196 | } | ||
| 197 | }, | ||
| 198 | Either::Second(req) => { | ||
| 199 | self.in_control_handler = true; | ||
| 200 | match req { | ||
| 201 | Setup::DataIn(req, stage) => self.handle_control_in(req, stage).await, | ||
| 202 | Setup::DataOut(req, stage) => self.handle_control_out(req, stage).await, | ||
| 203 | } | 184 | } |
| 204 | self.in_control_handler = false; | ||
| 205 | } | 185 | } |
| 186 | Either::Second(req) => match req { | ||
| 187 | Setup::DataIn(req, stage) => self.handle_control_in(req, stage).await, | ||
| 188 | Setup::DataOut(req, stage) => self.handle_control_out(req, stage).await, | ||
| 189 | }, | ||
| 206 | } | 190 | } |
| 207 | } | 191 | } |
| 208 | } | 192 | } |
| 209 | 193 | ||
| 194 | /// Disables the USB peripheral. | ||
| 210 | pub async fn disable(&mut self) { | 195 | pub async fn disable(&mut self) { |
| 211 | if self.device_state != UsbDeviceState::Disabled { | 196 | if self.device_state != UsbDeviceState::Disabled { |
| 212 | self.bus.disable().await; | 197 | self.bus.disable().await; |
| 213 | self.device_state = UsbDeviceState::Disabled; | 198 | self.device_state = UsbDeviceState::Disabled; |
| 214 | self.suspended = false; | 199 | self.suspended = false; |
| 215 | self.remote_wakeup_enabled = false; | 200 | self.remote_wakeup_enabled = false; |
| 216 | self.in_control_handler = false; | ||
| 217 | 201 | ||
| 218 | if let Some(h) = &self.handler { | 202 | if let Some(h) = &self.handler { |
| 219 | h.enabled(false); | 203 | h.enabled(false); |
| @@ -221,11 +205,26 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 221 | } | 205 | } |
| 222 | } | 206 | } |
| 223 | 207 | ||
| 208 | /// Waits for a resume condition on the USB bus. | ||
| 209 | /// | ||
| 210 | /// This future is cancel-safe. | ||
| 211 | pub async fn wait_resume(&mut self) { | ||
| 212 | while self.suspended { | ||
| 213 | let evt = self.bus.poll().await; | ||
| 214 | self.handle_bus_event(evt); | ||
| 215 | } | ||
| 216 | } | ||
| 217 | |||
| 218 | /// Initiates a device remote wakeup on the USB bus. | ||
| 219 | /// | ||
| 220 | /// If the bus is not suspended or remote wakeup is not enabled, an error | ||
| 221 | /// will be returned. | ||
| 222 | /// | ||
| 223 | /// This future may leave the bus in an inconsistent state if dropped. | ||
| 224 | /// After dropping the future, [`UsbDevice::disable()`] should be called | ||
| 225 | /// before calling any other `UsbDevice` methods to fully reset the peripheral. | ||
| 224 | pub async fn remote_wakeup(&mut self) -> Result<(), RemoteWakeupError> { | 226 | pub async fn remote_wakeup(&mut self) -> Result<(), RemoteWakeupError> { |
| 225 | if self.device_state == UsbDeviceState::Configured | 227 | if self.suspended && self.remote_wakeup_enabled { |
| 226 | && self.suspended | ||
| 227 | && self.remote_wakeup_enabled | ||
| 228 | { | ||
| 229 | self.bus.remote_wakeup().await?; | 228 | self.bus.remote_wakeup().await?; |
| 230 | self.suspended = false; | 229 | self.suspended = false; |
| 231 | 230 | ||
| @@ -239,6 +238,40 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 239 | } | 238 | } |
| 240 | } | 239 | } |
| 241 | 240 | ||
| 241 | fn handle_bus_event(&mut self, evt: Event) { | ||
| 242 | match evt { | ||
| 243 | Event::Reset => { | ||
| 244 | trace!("usb: reset"); | ||
| 245 | self.device_state = UsbDeviceState::Default; | ||
| 246 | self.suspended = false; | ||
| 247 | self.remote_wakeup_enabled = false; | ||
| 248 | self.pending_address = 0; | ||
| 249 | |||
| 250 | for (_, h) in self.interfaces.iter_mut() { | ||
| 251 | h.reset(); | ||
| 252 | } | ||
| 253 | |||
| 254 | if let Some(h) = &self.handler { | ||
| 255 | h.reset(); | ||
| 256 | } | ||
| 257 | } | ||
| 258 | Event::Resume => { | ||
| 259 | trace!("usb: resume"); | ||
| 260 | self.suspended = false; | ||
| 261 | if let Some(h) = &self.handler { | ||
| 262 | h.suspended(false); | ||
| 263 | } | ||
| 264 | } | ||
| 265 | Event::Suspend => { | ||
| 266 | trace!("usb: suspend"); | ||
| 267 | self.suspended = true; | ||
| 268 | if let Some(h) = &self.handler { | ||
| 269 | h.suspended(true); | ||
| 270 | } | ||
| 271 | } | ||
| 272 | } | ||
| 273 | } | ||
| 274 | |||
| 242 | async fn handle_control_out(&mut self, req: Request, stage: DataOutStage) { | 275 | async fn handle_control_out(&mut self, req: Request, stage: DataOutStage) { |
| 243 | const CONFIGURATION_NONE_U16: u16 = CONFIGURATION_NONE as u16; | 276 | const CONFIGURATION_NONE_U16: u16 = CONFIGURATION_NONE as u16; |
| 244 | const CONFIGURATION_VALUE_U16: u16 = CONFIGURATION_VALUE as u16; | 277 | const CONFIGURATION_VALUE_U16: u16 = CONFIGURATION_VALUE as u16; |
