Adafruit_CircuitPython_HID icon indicating copy to clipboard operation
Adafruit_CircuitPython_HID copied to clipboard

USB Keyboard no longer sends keystrokes after windows machine go to sleep

Open dillondriskill opened this issue 3 years ago • 14 comments

Issue is occurring with a RPi Pico running the most up to date circuit python, and hid library. The issue does not occur on mac machines (haven't tested linux) A power cycle of the RPi resolves the issue, however, unplugging and replugging my macro pad every time my pc goes to sleep is getting a little annoying.

I'm not really sure why this happens. I imagine it has to do with how windows handles "sleep" mode, probably still powering the device in some way, and somehow this messes with the device recognition, whereas mac probably just powers off the usb device? I'm not entirely sure..

In order to replicate this it's pretty simple:

  • Put circuitpython on a rpi pico
  • Put keyboard code device
  • Ensure the board works as expected
  • Put windows machine to sleep
  • Wake windows machine
  • Notice keyboard no longer sends keypresses

It could very well be sending the key presses, but windows isn't recognizing them. I have no idea, and I haven't been able to see anything about it online.

dillondriskill avatar May 07 '22 16:05 dillondriskill

Try inserting a delay of a few seconds before creating the Keyboard() object. Internally, the constructor has a delay: it tries once, and if that fails, it tries again, after waiting one second, but that may not be enough. https://github.com/adafruit/Adafruit_CircuitPython_HID/blob/b0c9fb0c92373c458adaa955656a7b8639716303/adafruit_hid/keyboard.py#L65-L71

dhalbert avatar May 07 '22 16:05 dhalbert

I see whats going on.

I also see now that this was mentioned in #93 and #15

Would it be possible to put this try/except statement in a while loop and break if it succeeds?

dillondriskill avatar May 07 '22 21:05 dillondriskill

So I've done some tests on my side, and found some interesting results...

I was intent on solving the issue at the root, so I downloaded the source and downloaded mpy-cross and made the edit I suggested in the previous comment, and still nothing changed.

After some trial and error with that, I decided to just do what you said and add a sleep(10) before I initialize the keyboard, and yet the issue persists. I do believe that still putting the while loop may fix this issue in some instances, however I do not believe that is the issue here.

dillondriskill avatar May 07 '22 22:05 dillondriskill

Yes, this could be a Windows sleep issue, somehow we are not recovering properly from that. I feel it also used to work for me (I have a Trinket M0 connected as a volume control), and sometimes I see problems now, but it's on Linux. I will try some experiments on Windows.

dhalbert avatar May 07 '22 22:05 dhalbert

Interesting. During my testing on my mac and windows machine i found that the issue would happen on windows both when I tell it to sleep from the power menu, or if it goes to sleep from being idle, whereas i was unable to replicate the issue on my M1 MacBook Air.

dillondriskill avatar May 08 '22 00:05 dillondriskill

This is also happening to me with a KB2040 with CircuitPython on a MacBook Pro. I built the keyboard as a Split keyboard, with two KB2040 connected with a TRRS cable.

I will try to experiment as well on a fix!

isacben avatar May 26 '22 15:05 isacben

@isacben any ideas? Have been AFK for a while, but looking to resolve this issue

dillondriskill avatar Aug 11 '22 04:08 dillondriskill

I have the same issue with a RP2040 as a custom USB keyboard controller. The keyboard will wake the PC from sleep, but then stops working and additionally hangs the computer for a while or gives a BSOD (driver power state failure or DPC watchdog violation). If I unplug the RP2040 device before putting the PC to sleep I have no issues. CircuitPython 7.3.2, Windows 11

jeffglancy avatar Aug 23 '22 23:08 jeffglancy

Aren't there any fixes/workarounds yet? I'm having the same problem.

Xitee1 avatar Dec 03 '22 17:12 Xitee1

My workaround is to catch the error for every event. try: kbd.press(key) except OSError: This prevents the RP2040 from crashing while the PC is asleep with the downside of not waking the PC.

jeffglancy avatar Dec 03 '22 21:12 jeffglancy

My workaround is to catch the error for every event. try: kbd.press(key) except OSError: This prevents the RP2040 from crashing while the PC is asleep with the downside of not waking the PC.

Thank you, that did work perfectly.

Xitee1 avatar Dec 04 '22 09:12 Xitee1

My workaround is to catch the error for every event. try: kbd.press(key) except OSError: This prevents the RP2040 from crashing while the PC is asleep with the downside of not waking the PC.

Thanks for the solution. I am having the same problem but before applying the code the rp2040 wasn't able to wake up the PC. were you able to wake up your PC sending the keyboard.press before caching the error?

dslrcnc avatar Jan 09 '23 12:01 dslrcnc

Thanks for the solution. I am having the same problem but before applying the code the rp2040 wasn't able to wake up the PC. were you able to wake up your PC sending the keyboard.press before caching the error?

It would wake the PC some of the time, but then often hang Windows with a BSOD, and the RP2040 would require a reboot.

jeffglancy avatar Jan 09 '23 15:01 jeffglancy

We have an open issue for this: it's something to do in the CircuitPython core: https://github.com/adafruit/circuitpython/issues/5380

dhalbert avatar Jan 09 '23 16:01 dhalbert