feat(usb): enable remote wakeup for HID devices#1235
feat(usb): enable remote wakeup for HID devices#1235adamshiervani merged 2 commits intojetkvm:devfrom
Conversation
bcc0cd5 to
ccde02b
Compare
adamshiervani
left a comment
There was a problem hiding this comment.
Thanks for the thorough PR description and testing — the benchmarks and powercfg /lastwake verification are excellent.
I reviewed both this PR and the companion kernel patch (rv1106-system#57). Two issues:
1. Backward compatibility: wakeup_on_write will break USB init on unpatched kernels
The wakeup_on_write attribute is added unconditionally to all three HID function configs. On devices running a kernel without rv1106-system#57, this configfs attribute won't exist. Walking through the changeset resolver:
getActualState()→ file doesn't exist →ActualState = FileStateAbsentgetFileChangeResolvedAction()forFileStateFileContentMatchwithActualState != FileStateFile→ returnsFileChangeResolvedActionCreateFileapplyChange()→os.WriteFile()on a non-existent configfs path → fails (configfs doesn't allow creating arbitrary files)IgnoreErrorsis not set → error propagates → entire USB gadget initialization fails
This means deploying this Go binary on a device without the patched kernel will break USB entirely — no keyboard, no mouse, no mass storage.
Options:
- Set
IgnoreErrors: trueon thewakeup_on_writeattribute writes - Detect kernel support (e.g. check if the attribute file exists before writing)
- Coordinate the rollout so the kernel patch always lands first (fragile)
The bmAttributes = 0xa0 change is also unconditional — advertising remote wakeup on a kernel that can't deliver it is misleading but not harmful.
2. Kernel patch (rv1106-system#57): potential NULL dereference in f_hidg_write
struct usb_composite_dev *cdev = hidg->func.config->cdev;This unconditionally dereferences hidg->func.config at the variable declaration, before the null checks on cdev and cdev->gadget. If config is NULL (e.g. during unbind racing with a write), this is a kernel NULL pointer dereference → oops/panic.
Yes, the existing code already accesses hidg->in_ep later with the same assumption, but this new dereference happens earlier (before the spinlock), widening the race window.
Suggested fix — move the dereference inside the guard:
if (hidg->wakeup_on_write && hidg->func.config) {
struct usb_composite_dev *cdev = hidg->func.config->cdev;
if (cdev && cdev->gadget)
usb_gadget_wakeup(cdev->gadget);
}Or at minimum, guard config:
struct usb_composite_dev *cdev = hidg->func.config ?
hidg->func.config->cdev : NULL;Everything else looks clean: the configfs registration follows the no_out_endpoint pattern, the hidg_alloc copy is consistent, and the Go-side config changes are minimal.
d26a3d7 to
b7a697a
Compare
|
@adamshiervani thanks for taking a look. Both PRs updated following review suggestions. |
Set bmAttributes to 0xa0 (bus-powered + remote wakeup) in the USB configuration descriptor, and enable wakeup_on_write on all HID functions (keyboard, absolute mouse, relative mouse). Together with the corresponding kernel f_hid patch in rv1106-system, this allows the JetKVM to wake a sleeping host by sending keyboard or mouse input through the web UI or API. Tested on JetKVM v2 waking a Windows 11 host from S3 sleep. Requires: jetkvm/rv1106-system kernel patch (f_hid wakeup_on_write) Closes: jetkvm#120 Closes: jetkvm#674
The wakeup_on_write configfs attribute only exists on kernels with the rv1106-system#57 patch. On unpatched kernels the attribute is absent, and writing to it fails, which would break the entire USB gadget initialization. Set IgnoreErrors for wakeup_on_write so it is silently skipped on kernels that lack the attribute.
b7a697a to
41c50f0
Compare
Fixes #120 and #674.
Summary
Enable USB remote wakeup so JetKVM can wake a sleeping host via keyboard or mouse input.
Requires the kernel-side
wakeup_on_writeconfigfs attribute from jetkvm/rv1106-system#57 to work end to end.Two changes:
bmAttributes = 0xa0(bus-powered + remote wakeup) in the USB configuration descriptor, advertising remote wakeup capability to the host during enumerationwakeup_on_write = 1on all three HID functions (keyboard, absolute mouse, relative mouse), so the kernel callsusb_gadget_wakeup()before each HID report writeChanges
config.go: AddbmAttributes: "0xa0"to gadget config attributeshid_keyboard.go: Addwakeup_on_write: "1"hid_mouse_absolute.go: Addwakeup_on_write: "1"hid_mouse_relative.go: Addwakeup_on_write: "1"Testing
Tested on JetKVM v2 with patched kernel (rv1106-system#57). Host: Windows 11 (S3 sleep), Intel Z390 chipset, xHCI controller.
Test setup
Descriptor verification
lsusb -von host confirms the configuration descriptor advertises remote wakeup:Test 1: Direct HID write via SSH (measures raw PC wake time)
SSH into JetKVM and write a raw keyboard HID report to the gadget device:
Measurement: timed from HID write completion to first successful ping response from the host.
powercfg /lastwakeconfirms wake source on every test:Note: the total SSH command time is dominated by SSH overhead to JetKVM's BusyBox shell on the RV1106. The actual HID write and USB wakeup are near-instant.
Test 2: Wake via JetKVM web UI (measures end-to-end user experience)
With the host asleep, pressed spacebar through the KVM web interface.
Measurement: JS polling
video.currentTimeevery 50ms in headful Chromium, detecting when the video stream advances >0.05s from the frozen baseline. This measures the full pipeline: HID write, PC wake, GPU resume, HDMI signal, JetKVM capture, WebRTC stream.The ~22s overhead beyond the raw 4s wake time is almost entirely Windows GPU resume (powering from D3, reinitializing display driver, outputting HDMI signal). This is outside JetKVM's control and will vary by GPU, driver version, and display configuration.
Test 3: Mouse input
Tested with both absolute and relative mouse movement through the web UI. Both wake the host successfully with the same timing.
Notes
Checklist
make test_e2elocally and passedNote
Medium Risk
Touches USB gadget descriptor/configfs attributes used during enumeration and runtime HID writes; behavior depends on kernel support for
wakeup_on_writeand could affect host compatibility if misconfigured.Overview
Advertises USB remote wakeup support by setting
bmAttributes = 0xa0on the base gadget configuration.Enables kernel-triggered wakeups on input by writing
wakeup_on_write = 1for keyboard and both mouse HID functions, and updates the configfs transaction writer to ignore errors whenwakeup_on_writeis unsupported (optional kernel feature).Written by Cursor Bugbot for commit 41c50f0. This will update automatically on new commits. Configure here.