Skip to content

Commit 5488c64

Browse files
authored
Address wake from sleep instability (qmk#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
1 parent eec3d32 commit 5488c64

File tree

5 files changed

+37
-5
lines changed

5 files changed

+37
-5
lines changed

docs/config_options.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ This is a C header file that is one of the first things included, and will persi
9797
* sets the maximum power (in mA) over USB for the device (default: 500)
9898
* `#define USB_POLLING_INTERVAL_MS 10`
9999
* sets the USB polling rate in milliseconds for the keyboard, mouse, and shared (NKRO/media keys) interfaces
100+
* `#define USB_SUSPEND_WAKEUP_DELAY 200`
101+
* set the number of milliseconde to pause after sending a wakeup packet
100102
* `#define F_SCL 100000L`
101103
* sets the I2C clock rate speed for keyboards using I2C. The default is `400000L`, except for keyboards using `split_common`, where the default is `100000L`.
102104

tmk_core/common/avr/suspend.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ static void power_down(uint8_t wdto) {
102102
# if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
103103
rgblight_suspend();
104104
# endif
105-
suspend_power_down_kb();
106105

107106
// TODO: more power saving
108107
// See PicoPower application note

tmk_core/common/suspend.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,7 @@ void suspend_wakeup_init_user(void);
1212
void suspend_wakeup_init_kb(void);
1313
void suspend_power_down_user(void);
1414
void suspend_power_down_kb(void);
15+
16+
#ifndef USB_SUSPEND_WAKEUP_DELAY
17+
# define USB_SUSPEND_WAKEUP_DELAY 200
18+
#endif

tmk_core/protocol/chibios/usb_main.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,17 @@ void init_usb_driver(USBDriver *usbp) {
708708
void restart_usb_driver(USBDriver *usbp) {
709709
usbStop(usbp);
710710
usbDisconnectBus(usbp);
711+
712+
#if USB_SUSPEND_WAKEUP_DELAY > 0
713+
// Some hubs, kvm switches, and monitors do
714+
// weird things, with USB device state bouncing
715+
// around wildly on wakeup, yielding race
716+
// conditions that can corrupt the keyboard state.
717+
//
718+
// Pause for a while to let things settle...
719+
wait_ms(USB_SUSPEND_WAKEUP_DELAY);
720+
#endif
721+
711722
usbStart(usbp, &usbcfg);
712723
usbConnectBus(usbp);
713724
}

tmk_core/protocol/lufa/lufa.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,9 @@ void EVENT_USB_Device_Suspend() {
435435
*/
436436
void EVENT_USB_Device_WakeUp() {
437437
print("[W]");
438+
#if defined(NO_USB_STARTUP_CHECK)
438439
suspend_wakeup_init();
440+
#endif
439441

440442
#ifdef SLEEP_LED_ENABLE
441443
sleep_led_disable();
@@ -1073,12 +1075,26 @@ int main(void) {
10731075
print("Keyboard start.\n");
10741076
while (1) {
10751077
#if !defined(NO_USB_STARTUP_CHECK)
1076-
while (USB_DeviceState == DEVICE_STATE_Suspended) {
1078+
if (USB_DeviceState == DEVICE_STATE_Suspended) {
10771079
print("[s]");
1078-
suspend_power_down();
1079-
if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
1080-
USB_Device_SendRemoteWakeup();
1080+
while (USB_DeviceState == DEVICE_STATE_Suspended) {
1081+
suspend_power_down();
1082+
if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
1083+
USB_Device_SendRemoteWakeup();
1084+
clear_keyboard();
1085+
1086+
# if USB_SUSPEND_WAKEUP_DELAY > 0
1087+
// Some hubs, kvm switches, and monitors do
1088+
// weird things, with USB device state bouncing
1089+
// around wildly on wakeup, yielding race
1090+
// conditions that can corrupt the keyboard state.
1091+
//
1092+
// Pause for a while to let things settle...
1093+
wait_ms(USB_SUSPEND_WAKEUP_DELAY);
1094+
# endif
1095+
}
10811096
}
1097+
suspend_wakeup_init();
10821098
}
10831099
#endif
10841100

0 commit comments

Comments
 (0)