mirror of https://github.com/jetkvm/kvm.git
Compare commits
3 Commits
af8fff7cee
...
7feb92c9c7
| Author | SHA1 | Date |
|---|---|---|
|
|
7feb92c9c7 | |
|
|
4592269dd1 | |
|
|
e1815237eb |
10
hidrpc.go
10
hidrpc.go
|
|
@ -109,6 +109,16 @@ func handleHidRPCKeyboardInput(message hidrpc.Message) (*usbgadget.KeysDownState
|
||||||
}
|
}
|
||||||
|
|
||||||
func reportHidRPC(params any, session *Session) {
|
func reportHidRPC(params any, session *Session) {
|
||||||
|
if session == nil {
|
||||||
|
logger.Warn().Msg("session is nil, skipping reportHidRPC")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !session.hidRPCAvailable || session.HidChannel == nil {
|
||||||
|
logger.Warn().Msg("HID RPC is not available, skipping reportHidRPC")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
message []byte
|
message []byte
|
||||||
err error
|
err error
|
||||||
|
|
|
||||||
|
|
@ -146,6 +146,8 @@ func (u *UsbGadget) GetKeysDownState() KeysDownState {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UsbGadget) updateKeyDownState(state KeysDownState) {
|
func (u *UsbGadget) updateKeyDownState(state KeysDownState) {
|
||||||
|
u.log.Trace().Interface("old", u.keysDownState).Interface("new", state).Msg("acquiring keyboardStateLock for updateKeyDownState")
|
||||||
|
|
||||||
u.keyboardStateLock.Lock()
|
u.keyboardStateLock.Lock()
|
||||||
defer u.keyboardStateLock.Unlock()
|
defer u.keyboardStateLock.Unlock()
|
||||||
|
|
||||||
|
|
@ -242,7 +244,7 @@ func (u *UsbGadget) keyboardWriteHidFile(modifier byte, keys []byte) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := writeWithTimeout(u.keyboardHidFile, append([]byte{modifier, 0x00}, keys[:hidKeyBufferSize]...))
|
_, err := u.writeWithTimeout(u.keyboardHidFile, append([]byte{modifier, 0x00}, keys[:hidKeyBufferSize]...))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
u.logWithSuppression("keyboardWriteHidFile", 100, u.log, err, "failed to write to hidg0")
|
u.logWithSuppression("keyboardWriteHidFile", 100, u.log, err, "failed to write to hidg0")
|
||||||
u.keyboardHidFile.Close()
|
u.keyboardHidFile.Close()
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ func (u *UsbGadget) absMouseWriteHidFile(data []byte) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := writeWithTimeout(u.absMouseHidFile, data)
|
_, err := u.writeWithTimeout(u.absMouseHidFile, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
u.logWithSuppression("absMouseWriteHidFile", 100, u.log, err, "failed to write to hidg1")
|
u.logWithSuppression("absMouseWriteHidFile", 100, u.log, err, "failed to write to hidg1")
|
||||||
u.absMouseHidFile.Close()
|
u.absMouseHidFile.Close()
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ func (u *UsbGadget) relMouseWriteHidFile(data []byte) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := writeWithTimeout(u.relMouseHidFile, data)
|
_, err := u.writeWithTimeout(u.relMouseHidFile, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
u.logWithSuppression("relMouseWriteHidFile", 100, u.log, err, "failed to write to hidg2")
|
u.logWithSuppression("relMouseWriteHidFile", 100, u.log, err, "failed to write to hidg2")
|
||||||
u.relMouseHidFile.Close()
|
u.relMouseHidFile.Close()
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ func compareFileContent(oldContent []byte, newContent []byte, looserMatch bool)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeWithTimeout(file *os.File, data []byte) (n int, err error) {
|
func (u *UsbGadget) writeWithTimeout(file *os.File, data []byte) (n int, err error) {
|
||||||
if err := file.SetWriteDeadline(time.Now().Add(hidWriteTimeout)); err != nil {
|
if err := file.SetWriteDeadline(time.Now().Add(hidWriteTimeout)); err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
|
@ -121,6 +121,14 @@ func writeWithTimeout(file *os.File, data []byte) (n int, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if errors.Is(err, os.ErrDeadlineExceeded) {
|
if errors.Is(err, os.ErrDeadlineExceeded) {
|
||||||
|
u.logWithSuppression(
|
||||||
|
fmt.Sprintf("writeWithTimeout_%s", file.Name()),
|
||||||
|
1000,
|
||||||
|
u.log,
|
||||||
|
err,
|
||||||
|
"write timed out: %s",
|
||||||
|
file.Name(),
|
||||||
|
)
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -229,6 +229,7 @@ export default function WebRTCVideo() {
|
||||||
if (rpcHidReady) {
|
if (rpcHidReady) {
|
||||||
reportRelMouseEvent(dx, dy, buttons);
|
reportRelMouseEvent(dx, dy, buttons);
|
||||||
} else {
|
} else {
|
||||||
|
// kept for backward compatibility
|
||||||
send("relMouseReport", { dx, dy, buttons });
|
send("relMouseReport", { dx, dy, buttons });
|
||||||
}
|
}
|
||||||
setMouseMove({ x, y, buttons });
|
setMouseMove({ x, y, buttons });
|
||||||
|
|
@ -260,6 +261,7 @@ export default function WebRTCVideo() {
|
||||||
if (rpcHidReady) {
|
if (rpcHidReady) {
|
||||||
reportAbsMouseEvent(x, y, buttons);
|
reportAbsMouseEvent(x, y, buttons);
|
||||||
} else {
|
} else {
|
||||||
|
// kept for backward compatibility
|
||||||
send("absMouseReport", { x, y, buttons });
|
send("absMouseReport", { x, y, buttons });
|
||||||
}
|
}
|
||||||
// We set that for the debug info bar
|
// We set that for the debug info bar
|
||||||
|
|
|
||||||
|
|
@ -51,26 +51,13 @@ export default function useKeyboard() {
|
||||||
if (rpcHidReady) {
|
if (rpcHidReady) {
|
||||||
console.debug("Sending keyboard report via HidRPC");
|
console.debug("Sending keyboard report via HidRPC");
|
||||||
reportKeyboardEvent(state.keys, state.modifier);
|
reportKeyboardEvent(state.keys, state.modifier);
|
||||||
|
setkeyPressReportApiAvailable(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
send("keyboardReport", { keys: state.keys, modifier: state.modifier }, (resp: JsonRpcResponse) => {
|
send("keyboardReport", { keys: state.keys, modifier: state.modifier }, (resp: JsonRpcResponse) => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
console.error(`Failed to send keyboard report ${state}`, resp.error);
|
console.error(`Failed to send keyboard report ${state}`, resp.error);
|
||||||
} else {
|
|
||||||
// If the device supports keyPressReport API, it will (also) return the keysDownState when we send
|
|
||||||
// the keyboardReport
|
|
||||||
const keysDownState = resp.result as KeysDownState;
|
|
||||||
|
|
||||||
if (keysDownState) {
|
|
||||||
setKeysDownState(keysDownState); // treat the response as the canonical state
|
|
||||||
setkeyPressReportApiAvailable(true); // if they returned a keysDownState, we ALSO know they also support keyPressReport
|
|
||||||
} else {
|
|
||||||
// older devices versions do not return the keyDownState
|
|
||||||
// so we just pretend they accepted what we sent
|
|
||||||
setKeysDownState(state);
|
|
||||||
setkeyPressReportApiAvailable(false); // we ALSO know they do not support keyPressReport
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
@ -79,7 +66,6 @@ export default function useKeyboard() {
|
||||||
rpcHidReady,
|
rpcHidReady,
|
||||||
send,
|
send,
|
||||||
reportKeyboardEvent,
|
reportKeyboardEvent,
|
||||||
setKeysDownState,
|
|
||||||
setkeyPressReportApiAvailable,
|
setkeyPressReportApiAvailable,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
@ -92,41 +78,14 @@ export default function useKeyboard() {
|
||||||
// in client/browser-side code using simulateDeviceSideKeyHandlingForLegacyDevices.
|
// in client/browser-side code using simulateDeviceSideKeyHandlingForLegacyDevices.
|
||||||
const sendKeypressEvent = useCallback(
|
const sendKeypressEvent = useCallback(
|
||||||
async (key: number, press: boolean) => {
|
async (key: number, press: boolean) => {
|
||||||
if (rpcDataChannel?.readyState !== "open" && !rpcHidReady) return;
|
|
||||||
|
|
||||||
console.debug(`Send keypressEvent key: ${key}, press: ${press}`);
|
console.debug(`Send keypressEvent key: ${key}, press: ${press}`);
|
||||||
|
|
||||||
if (rpcHidReady) {
|
if (!rpcHidReady) return;
|
||||||
console.debug("Sending keypress event via HidRPC");
|
|
||||||
reportKeypressEvent(key, press);
|
reportKeypressEvent(key, press);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
send("keypressReport", { key, press }, (resp: JsonRpcResponse) => {
|
|
||||||
if ("error" in resp) {
|
|
||||||
// -32601 means the method is not supported because the device is running an older version
|
|
||||||
if (resp.error.code === -32601) {
|
|
||||||
console.error("Legacy device does not support keypressReport API, switching to local key down state handling", resp.error);
|
|
||||||
setkeyPressReportApiAvailable(false);
|
|
||||||
} else {
|
|
||||||
console.error(`Failed to send key ${key} press: ${press}`, resp.error);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const keysDownState = resp.result as KeysDownState;
|
|
||||||
|
|
||||||
if (keysDownState) {
|
|
||||||
setKeysDownState(keysDownState);
|
|
||||||
// we don't need to set keyPressReportApiAvailable here, because it's already true or we never landed here
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
rpcDataChannel?.readyState,
|
|
||||||
rpcHidReady,
|
rpcHidReady,
|
||||||
send,
|
|
||||||
setkeyPressReportApiAvailable,
|
|
||||||
setKeysDownState,
|
|
||||||
reportKeypressEvent,
|
reportKeypressEvent,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue