From 8d71a358c8fa0524fce564357d3d36f24be41353 Mon Sep 17 00:00:00 2001
From: huntc <huntchr@gmail.com>
Date: Fri, 8 Jul 2022 15:30:15 +1000
Subject: [PATCH] Build in a new Unpowered state

Replaces the sub-state of representing being being available. Power states also now set enable/disable directly too, which simplifies code.
---
 embassy-usb/src/lib.rs | 45 ++++++++++++++++++++----------------------
 1 file changed, 21 insertions(+), 24 deletions(-)

diff --git a/embassy-usb/src/lib.rs b/embassy-usb/src/lib.rs
index af102e589..82ff4e32f 100644
--- a/embassy-usb/src/lib.rs
+++ b/embassy-usb/src/lib.rs
@@ -30,6 +30,9 @@ use crate::driver::ControlPipe;
 #[derive(PartialEq, Eq, Copy, Clone, Debug)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub enum UsbDeviceState {
+    /// The USB device has no power.
+    Unpowered,
+
     /// The USB device is disabled.
     Disabled,
 
@@ -114,7 +117,6 @@ struct Inner<'d, D: Driver<'d>> {
 
     device_state: UsbDeviceState,
     suspended: bool,
-    power_available: bool,
     remote_wakeup_enabled: bool,
     self_powered: bool,
 
@@ -155,9 +157,8 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
                 config_descriptor,
                 bos_descriptor,
 
-                device_state: UsbDeviceState::Disabled,
+                device_state: UsbDeviceState::Unpowered,
                 suspended: false,
-                power_available: false,
                 remote_wakeup_enabled: false,
                 self_powered: false,
                 address: 0,
@@ -187,25 +188,11 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
     /// before calling any other `UsbDevice` methods to fully reset the
     /// peripheral.
     pub async fn run_until_suspend(&mut self) -> () {
-        while !self.inner.power_available {
-            let evt = self.inner.bus.poll().await;
-            self.inner.handle_bus_event(evt);
-        }
-
-        if self.inner.device_state == UsbDeviceState::Disabled {
-            self.inner.bus.enable().await;
-            self.inner.device_state = UsbDeviceState::Default;
-
-            if let Some(h) = &self.inner.handler {
-                h.enabled(true);
-            }
-        }
-
-        while !self.inner.suspended && self.inner.power_available {
+        while !self.inner.suspended {
             let control_fut = self.control.setup();
             let bus_fut = self.inner.bus.poll();
             match select(bus_fut, control_fut).await {
-                Either::First(evt) => self.inner.handle_bus_event(evt),
+                Either::First(evt) => self.inner.handle_bus_event(evt).await,
                 Either::Second(req) => self.handle_control(req).await,
             }
         }
@@ -229,9 +216,9 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
     ///
     /// This future is cancel-safe.
     pub async fn wait_resume(&mut self) {
-        while self.inner.suspended || !self.inner.power_available {
+        while self.inner.suspended {
             let evt = self.inner.bus.poll().await;
-            self.inner.handle_bus_event(evt);
+            self.inner.handle_bus_event(evt).await;
         }
     }
 
@@ -348,7 +335,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> {
 }
 
 impl<'d, D: Driver<'d>> Inner<'d, D> {
-    fn handle_bus_event(&mut self, evt: Event) {
+    async fn handle_bus_event(&mut self, evt: Event) {
         match evt {
             Event::Reset => {
                 trace!("usb: reset");
@@ -385,11 +372,21 @@ impl<'d, D: Driver<'d>> Inner<'d, D> {
             }
             Event::PowerDetected => {
                 trace!("usb: power detected");
-                self.power_available = true;
+                self.bus.enable().await;
+                self.device_state = UsbDeviceState::Default;
+
+                if let Some(h) = &self.handler {
+                    h.enabled(true);
+                }
             }
             Event::PowerRemoved => {
                 trace!("usb: power removed");
-                self.power_available = false;
+                self.bus.disable().await;
+                self.device_state = UsbDeviceState::Unpowered;
+
+                if let Some(h) = &self.handler {
+                    h.enabled(false);
+                }
             }
         }
     }
