mirror of
https://github.com/jetkvm/kvm.git
synced 2026-05-21 05:20:35 +00:00
dev
4 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
c08f14ff3f |
fix: send mouse button state changes via reliable WebRTC channel (#695) (#1338)
* fix: send mouse button state changes via reliable WebRTC channel (#695) When holding one mouse button and pressing another without moving the mouse, only pointerdown/pointerup events fire (no mousemove to self-correct). These button-only state changes were sent via the unreliable WebRTC data channel (maxRetransmits: 0), and lost packets were never recovered. Changes: - useHidRpc.ts: Track last button state and send button changes via the reliable channel. Movement-only events continue using the unreliable channel for low latency, since lost movement packets self-correct via subsequent mousemove events. - e2e/remote-agent/main.go: Fix omitempty on InputEvent.Value so button release events (value=0) are included in JSON responses. - ra-all.spec.ts: Add E2E test that holds left mouse button, presses and releases right mouse button, and verifies all 4 button events arrive on the remote host (20 iterations). * fix: rebuild remote agent when source changes to prevent stale deploys ensureDeployed() skipped rebuild and redeploy when the agent was already running, causing the omitempty fix on InputEvent.Value to never reach the remote host. Now compares source mtime against binary mtime and forces redeploy when a rebuild occurs. |
||
|
|
203c6ae6fd |
fix: recover HID chardev after DWC3 rebind race on RV1106 (#1366)
* fix: reset USB gadget when virtual media unmount fails with EBUSY (#834) When unmountImageLocked() gets EBUSY from the kernel (host OS still accessing the virtual disk via PREVENT MEDIUM REMOVAL), fall back to gadget.RebindUsb(true) to force-disconnect the host, then retry the unmount. Uses RebindUsb directly instead of UpdateGadgetConfig to avoid hitting the same EBUSY when writing configfs attributes before rebind. After rebind, properly reopen keyboard HID file (ResetHIDFiles + sleep + OpenKeyboardHidFile) matching the pattern in setMassStorageMode(). Also propagate unmount errors to RPC callers and only clear currentVirtualMediaState after the unmount actually succeeds. Adds E2E test that mounts an ISO on the remote host to trigger PREVENT MEDIUM REMOVAL, then verifies unmount succeeds and keyboard recovers. * fix: recover HID chardev after DWC3 rebind race on RV1106 The DWC3 USB controller on the RV1106 has a race condition where rapid unbind→bind of the UDC can permanently corrupt HID chardev state — /dev/hidg0 returns ENXIO even though the device node exists and the UDC shows "configured". This can be triggered by UpdateGadgetConfig's transaction rebind and by host-initiated USB device resets during mass storage media changes. Three-part fix: 1. rebindUsb(): after binding, verify /dev/hidg0 is openable. If not, unbind again with a 100ms pause for kernel cleanup, then rebind. 2. setMassStorageMode(): pre-set recovery timer before UpdateGadgetConfig to prevent the poller from interfering. After the 1s sleep, if OpenKeyboardHidFile fails, do a corrective RebindUsb + retry. 3. checkUSBState() poller: when a state transition occurs and OpenKeyboardHidFile fails, trigger a corrective rebind to recover from host-initiated USB resets that corrupt the chardev. * fix: suppress USB recovery poller before rebind in unmount and mode-change paths The auto-recovery poller could see transient "not attached" UDC state during RebindUsb and trigger a competing rebind, corrupting HID chardev state. Add setUSBRecoveryTimer calls before the rebind in unmountImageLocked and before the corrective rebind in setMassStorageMode. * test: replace blind sleep with two-phase wait in factory-reset e2e test Wait for device to become unreachable before polling for it to come back, preventing false passes from stale pre-reset responses. * refactor: simplify branch — extract helpers, remove duplication, fix flaky tests - Extract rebindAndRecoverHID() in Go to deduplicate USB recovery sequences - Remove redundant setUSBRecoveryTimer() call after UpdateGadgetConfig() - Extract waitForKeyboardReady() helper replacing 5 duplicate retry loops - Consolidate 3 duplicate remoteExec definitions into single remoteHostExec() - Use shared SSH_OPTS from helpers.ts instead of hardcoded SSH options - Fix remote agent omitempty on mouse X/Y causing undefined in TypeScript - Poll keys-down state in disconnect test to avoid race condition * fix: remove dead IsHidgChardevHealthy export, reset HID files before rebind - Remove unused exported IsHidgChardevHealthy wrapper (only the unexported isHidgChardevHealthy is called, inside rebindUsb) - Move ResetHIDFiles() before RebindUsb in checkUSBState so stale file handles are closed even if the rebind fails — prevents silent mouse write failures on dead inodes after a successful unbind + failed bind |
||
|
|
cf7215411d |
feat: add horizontal mouse wheel scrolling support (#415) (#1358)
* fix: add horizontal mouse wheel (AC Pan) scroll support (#415) - HID descriptors: add AC Pan (Usage 0x0238, Consumer Page) to both absolute and relative mouse descriptors for horizontal scroll - Backend: extend AbsMouseWheelReport to accept wheelX, add RelMouseWheelReport with both axes, update report_length - RPC: add wheelX parameter to wheelReport binding - Frontend: read deltaX in wheel handler with same clamping/inversion and throttling as vertical scroll - E2E: add wheel scroll test verifying both vertical (REL_WHEEL) and horizontal (REL_HWHEEL) events reach the remote host * style: fix goimports alignment in RelMouseReport * fix: don't negate horizontal scroll direction in wheelReport The clampWheel helper was negating the result for both axes, but only vertical scrolling needs inversion (browser deltaY and HID Wheel use opposite sign conventions). Horizontal scrolling (deltaX / AC Pan) shares the same convention (positive = right), so negation reversed the direction on the target machine. * fix: wire RelMouseWheelReport into RPC and add wheel scroll e2e tests rpcWheelReport only called AbsMouseWheelReport, so wheel scrolling was silently broken in relative-only mouse mode. Now calls both Abs and Rel wheel report methods (each guards on its own enabledDevices flag). Adds e2e tests for vertical/horizontal wheel scroll in default mode and relative-only mode. Bumps beforeAll waitForInputDevices timeout to 30s and keyboard LED test expectKeyPress timeouts to 5s to reduce flakiness. |
||
|
|
15dc380062 |
fix: auto-recover USB gadget when host power-cycles (#1297)
* fix: auto-recover USB gadget when host reconnects (#128) When the USB host reboots or disconnects, the UDC state becomes "not attached" and never recovers. Add automatic recovery that detects this state and rebinds the USB gadget, with rate limiting to avoid thrashing. Also refactor keyboard HID file handling to support force-reopen after rebind. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: move USB recovery logic to internal/usbgadget package Extract ShouldAttemptUSBRecovery and its retry interval constant into the internal/usbgadget package so the logic is testable without importing the top-level kvm package. Reset the recovery timer in updateUsbRelatedConfig to prevent auto-recovery from interfering during the host's USB re-enumeration window after a deliberate config change. Made-with: Cursor * feat(e2e): add JSON-RPC data channel support to test hooks Expose the WebRTC RPC data channel through test hooks and add a sendJsonRpc helper that sends a JSON-RPC request over the channel and resolves via callback with timeout handling. This enables e2e tests to invoke backend RPC methods directly. Made-with: Cursor * refactor(e2e): restructure tests with remote-agent suite Move device-level e2e tests (config-reset, EDID, HTTPS, HDMI sleep, LED, mouse, USB attach timing, USB device) into a consolidated remote-agent suite that runs through a Go-based agent binary. Add a separate Playwright project for remote-agent tests. - Remove standalone spec files now covered by ra-all.spec.ts - Rename login-rate-limit to zz-login-rate-limit so it runs last (avoids needing a post-test reboot to clear rate-limit state) - Reorder welcome-password tests so validation runs first, reusing the onboarding state and saving an SSH reset cycle Made-with: Cursor * refactor(e2e): clean up test helpers and reduce duplication Consolidate all test helpers into a single helpers.ts file, removing the separate ota-helpers.ts. This gives every test file a single import source and eliminates duplicated code across the test suite. Key changes: - Merge ota-helpers.ts into helpers.ts (mock server, binary deployment, device config, env var validation, triggerUpdate, withTempSignature) - Remove duplicated rpc/restartAppViaSSH/waitForDeviceReady functions from ra-all.spec.ts in favour of shared imports - Extract loginAndOpenSettings helper in settings-local-auth tests - Extract getOTAEnvVars, toPreReleaseVersion, triggerUpdate, and withTempSignature to reduce boilerplate across OTA tests - Remove unused verifyMouseWorks function and dead variables - Strip redundant JSDoc that just restated type signatures - Remove duplicated per-project use config from playwright.config.ts (already inherited from top-level) - Convert dynamic imports in sshExec to top-level imports Made-with: Cursor * refactor(e2e): move binary deployment into Playwright globalSetup Replace the shell-script deployment logic with Playwright's globalSetup/globalTeardown hooks. When BASELINE_BINARY_PATH is set, globalSetup deploys the binary, resets device config, reboots, and captures pre-test logs. globalTeardown captures post-test logs. This keeps the deployment lifecycle inside Playwright where it belongs, and reduces test_core_e2e.sh to a thin wrapper that sets env vars. Made-with: Cursor * fix: retry HID file reopen after USB gadget rebind After rebinding the DWC3 USB controller, the kernel needs a moment to create the /dev/hidg* device nodes. The previous code attempted to reopen the keyboard HID file immediately after rebind, which raced with the kernel and failed with "no such device or address". Add a retry loop (up to 10 attempts, 200ms apart) to wait for the device nodes to appear before reopening the keyboard HID file. Made-with: Cursor * fix: harden USB gadget recovery after UDC unbind Reset stale HID gadget handles after rebind, suppress transient HID-open errors during detach windows, and fall back to full gadget reconfiguration when simple UDC rebind does not restore keyboard HID promptly. Strengthen the remote-agent USB recovery E2E to verify both keyboard and mouse input recover after unbind with retry tolerance for host-side input node churn. Made-with: Cursor * refactor: simplify USB HID error handling and reduce hot-path overhead - Use errors.Is with syscall.Errno instead of string matching in IsHIDTemporarilyUnavailableError (robust, zero-alloc) - Cache USB state in usbReadyForHidReports instead of reading sysfs on every HID report - Extract rpcHidReport wrapper to deduplicate 5 rpc*Report functions - Fix openWithTimeout goroutine/fd leak on timeout - Add USBStateNotAttached/USBStateUnknown constants, replace literals - Deduplicate discoverJetKVMDevices by delegating to listInputDevices Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: run remote-agent e2e tests when JETKVM_REMOTE_HOST is provided Made-with: Cursor --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |