adafruit / Adafruit_CircuitPython_HID

USB Human Interface Device drivers.
MIT License
377 stars 105 forks source link

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

Open dillondriskill opened 2 years ago

dillondriskill commented 2 years ago

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:

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.

dhalbert commented 2 years ago

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

dillondriskill commented 2 years ago

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 commented 2 years ago

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.

dhalbert commented 2 years ago

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.

dillondriskill commented 2 years ago

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.

isacben commented 2 years ago

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!

dillondriskill commented 2 years ago

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

jeffglancy commented 2 years ago

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

Xitee1 commented 1 year ago

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

jeffglancy commented 1 year ago

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.

Xitee1 commented 1 year ago

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.

dslrcnc commented 1 year ago

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?

jeffglancy commented 1 year ago

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.

dhalbert commented 1 year ago

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