Qt Py ESP32 as USB Keyboard to Wake PC

For Adafruit customers who seek help with microcontrollers

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
tojo4158
 
Posts: 6
Joined: Thu Aug 11, 2022 12:04 am

Qt Py ESP32 as USB Keyboard to Wake PC

Post by tojo4158 »

I've just spent the last couple days trying to figure this out and since I didn't have any luck finding the answers directly online, I thought I'd share for anyone else that might be trying to do the same thing.

Also, if this is an obvious solution, I do apologize. I have years of coding experience but this is my first project with a Qt Py board and the Arduino IDE, so it was not so obvious to me.

Goal: Use my Qt Py ESP32-S2 to emulate a USB keyboard and upon some condition (I used a special UDP packet) wakeup the PC that is attached via USB.

I was able to follow examples easy enough to emulate a keyboard, but I could not initially figure out how to execute the wakeup. I had started programming my Qt Py with Circuit Python, but upon hitting this snag and doing a little digging, I decided Circuit Python might not have everything needed to make it work. So I switched to the Arduino IDE and the arduino-esp32 core (there were instructions on how to set this up on the Qt Py board overview page).

Again, I was able to get the basic USB keyboard emulation setup, but no luck on wakeup. I then tried installing the Adafruit TinyUSB library via the IDE library manager. Although the core seemed to already include TinyUSB, the core USB classes (ex: USBHIDKeyboard) didn't seem to expose any methods to actually wake the host. The Adafruit TinyUSB classes (ex: Adafruit_USBD_Device) exposed a method called remoteWakeup(). Looked very promising but did not work.

Upon doing some investigation (Windows 10 Device Manager), found that my USB keyboard could not be selected to "Allow Device to Wake Computer". This option was greyed out. A little research informed me that this was probably because the Remote Wakeup configuration descriptor was not being applied to the USB device when created. So I went digging for a way to set this config.

I eventually traced the code back to a core USB class ESPUSB (in packages/esp32/hardware/esp32/2.0.4/cores/esp32/USB.cpp). In this file, the ESPUSB constructor creates the config descriptors upon instantiation through its initializers. This line:

Code: Select all

usb_attributes(TUSB_DESC_CONFIG_ATT_SELF_POWERED)
added the config descriptor indicating the device was self powered, but did not add the descriptor that it could cause a host wakeup. The constructor also starts the USB device and there's no way to change the configuration after the device is started.

I eventually ended up modifying that line in the core USB.cpp file to this:

Code: Select all

usb_attributes(TUSB_DESC_CONFIG_ATT_SELF_POWERED | TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP)
Once I did that, Windows reported that my device had the option to wake the PC and when I called the remoteWakeup() function, it actually woke the host PC up!

I'm not an expert in this SDK, but I suspect the USB gets initialized and configured right away because the USB is such an integrated function of the ESP32-S2. I also believe that since I modified this line, any USB device that I create will now show wakeup as an option to the host.

Anyway, I wouldn't call it good practice to modify core SDK files, but that was the only way I could get it to work and now it's documented for others. If you know of a better way, please feel free to add on.

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: Qt Py ESP32 as USB Keyboard to Wake PC

Post by adafruit_support_mike »

That's good research.. thanks for posting a description of the problem and its solution!

Locked
Please be positive and constructive with your questions and comments.

Return to “Microcontrollers”