diff options
author | Joshua Diamond <josh@windowoffire.com> | 2021-02-01 19:12:41 -0500 |
---|---|---|
committer | Drashna Jael're <drashna@live.com> | 2021-02-02 09:29:51 -0800 |
commit | 0aaf72a2b9bef2fb035f03dfa14fdbd6ef01fbfb (patch) | |
tree | 837806eeb0d28a3c01592b70bca10caf756ddcc5 | |
parent | 9ee0271c00c05ee5dddb7d77b04b5ec2fac2bd41 (diff) |
Address wake from sleep instability (#11450)
* resolve race condition between suspend and wake in LUFA
* avoid multiple calls to suspend_power_down() / suspend_wakeup_init()
* Remove duplicate suspend_power_down_kb() call
* pause on wakeup to wait for USB state to settle
* need the repeated suspend_power_down() (that's where the sleep is)
* more efficient implementation
* fine tune the pause after sending wakeup
* speculative chibios version of pause-after-wake
* make wakeup delay configurable, and adjust value
* better location for wakeup delay
-rw-r--r-- | tmk_core/common/avr/suspend.c | 1 | ||||
-rw-r--r-- | tmk_core/common/suspend.h | 4 | ||||
-rw-r--r-- | tmk_core/protocol/chibios/usb_main.c | 11 | ||||
-rw-r--r-- | tmk_core/protocol/lufa/lufa.c | 24 |
4 files changed, 35 insertions, 5 deletions
diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c index a879d6bab0..807c837e36 100644 --- a/tmk_core/common/avr/suspend.c +++ b/tmk_core/common/avr/suspend.c @@ -110,7 +110,6 @@ static void power_down(uint8_t wdto) { rgblight_disable_noeeprom(); } # endif - suspend_power_down_kb(); // TODO: more power saving // See PicoPower application note diff --git a/tmk_core/common/suspend.h b/tmk_core/common/suspend.h index 766df95aa1..9d17d984ed 100644 --- a/tmk_core/common/suspend.h +++ b/tmk_core/common/suspend.h @@ -12,3 +12,7 @@ void suspend_wakeup_init_user(void); void suspend_wakeup_init_kb(void); void suspend_power_down_user(void); void suspend_power_down_kb(void); + +#ifndef USB_SUSPEND_WAKEUP_DELAY +# define USB_SUSPEND_WAKEUP_DELAY 200 +#endif diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index 4e3176ab26..67ae8520fd 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c @@ -701,6 +701,17 @@ void init_usb_driver(USBDriver *usbp) { void restart_usb_driver(USBDriver *usbp) { usbStop(usbp); usbDisconnectBus(usbp); + +#if USB_SUSPEND_WAKEUP_DELAY > 0 + // Some hubs, kvm switches, and monitors do + // weird things, with USB device state bouncing + // around wildly on wakeup, yielding race + // conditions that can corrupt the keyboard state. + // + // Pause for a while to let things settle... + wait_ms(USB_SUSPEND_WAKEUP_DELAY); +#endif + usbStart(usbp, &usbcfg); usbConnectBus(usbp); } diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index ce31e54990..3c6b1cffaf 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -498,7 +498,9 @@ void EVENT_USB_Device_Suspend() { */ void EVENT_USB_Device_WakeUp() { print("[W]"); +#if defined(NO_USB_STARTUP_CHECK) suspend_wakeup_init(); +#endif #ifdef SLEEP_LED_ENABLE sleep_led_disable(); @@ -1184,12 +1186,26 @@ int main(void) { print("Keyboard start.\n"); while (1) { #if !defined(NO_USB_STARTUP_CHECK) - while (USB_DeviceState == DEVICE_STATE_Suspended) { + if (USB_DeviceState == DEVICE_STATE_Suspended) { print("[s]"); - suspend_power_down(); - if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) { - USB_Device_SendRemoteWakeup(); + while (USB_DeviceState == DEVICE_STATE_Suspended) { + suspend_power_down(); + if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) { + USB_Device_SendRemoteWakeup(); + clear_keyboard(); + +# if USB_SUSPEND_WAKEUP_DELAY > 0 + // Some hubs, kvm switches, and monitors do + // weird things, with USB device state bouncing + // around wildly on wakeup, yielding race + // conditions that can corrupt the keyboard state. + // + // Pause for a while to let things settle... + wait_ms(USB_SUSPEND_WAKEUP_DELAY); +# endif + } } + suspend_wakeup_init(); } #endif |